web-dev-qa-db-ja.com

errnoの値を確認する方法は?

私はシステムコールを使用していますが、失敗した場合は、異なるerrnoに対して異なることをする必要があります。

次のようなコードを書く必要があります。

int res;
res = systemCall();
if (res == -1)
{
    if (errno == ENOMSG)
    {
        doSomething();
    }
    else
    {
        doSomethingElse();
    }
}

perrorは値を出力するだけなので、役に立ちません。

Strerroに関しては、もしそれが私が必要なものであるなら、私はそれを使う方法を求めていません。なぜなら、 here は実際の文字列はエラーと同じではないと言うからです。マニュアルページから引用:「(たとえば、errnumがEINVALの場合、返される説明は「無効な引数」になります)」。

Linuxを使用しています。システムコール:msgsendおよびmsgrcv( https://linux.die.net/man/2/msgrcv )。あなたがどんなCライブラリを求めているのか分かりません。

私は自分自身をうまく説明しなかったようです。

If(errno == ENOMSG)ステートメントは有効ですか?そのような変数errnoはありますか?基本的に私の質問は次のとおりです:errnoをテストするためにifステートメントに何を入れるべきですか?

7
Hana

私はあなたがLinuxを使用していると仮定し、直接システムコールを使用しないと仮定しますが、いくつかの(単純な)ラッパー( Cライブラリ) syscalls(2) にリストされています。いくつかの奇妙なシステムコールはCライブラリによってラップされないことに注意してください(ラップされていないシステムコールのよく知られた例は sigreturn(2) で、おそらく決して使用すべきではありません)。多くの場合、Cライブラリは GNU glibc ですが、 musl-libc などになる可能性があります。また、カーネルrawシステムコールは異なる 呼び出し規約 であることに注意してください。通常のC関数よりも(したがって、実際にはlibcラッパーが必要であり、errnoの処理を担当します)。また、 errno(3) は一般にマクロであることに注意してください(ほとんど変数として動作します)。

msgrcv(2) manページには、errnoが_E2BIG_、EACCESEFAULT ... ENOMSGのいずれかであることが記載されています、ENOSYS ...(そのマニュアルページを参照して、考えられるすべてのエラーのリストを取得してください)。

だからあなたは次のようなコードを書くでしょう

_ssize_t siz = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
if (siz<0) { // msgrcv failed and has set errno
  if (errno == ENOMSG) 
    dosomething();
  else if (errno == EAGAIN) 
    dosomethingelse();
  /// etc
  else {  
     syslog(LOG_DAEMON|LOG_ERR, "msgrcv failure with %s\n",
            strerror(errno)); 
     exit(EXIT_FAILURE); 
  };
};
_

ステートメントif (errno == ENOMSG) ....は有効ですか?

はい、そうです; errnoをテストするには、何らかのシステムコールが失敗した後でのみ(たとえば、_siz<0_の場合)。

そのような変数errnoはありますか?

もう違います。注意深くお読みください errno(3) documentation _extern int errno;_を宣言しないでください(これは21ではなく1980年代に可能でした。st 世紀)しかし、always_#include <errno.h>_であり、変数であるかのようにerrnoを使用する必要がありますが、ほとんどの場合は何らかのマクロです(その定義は_/usr/include/bits/errno.h_に含まれる_/usr/include/errno.h_に表示されます)。

ところで、SysVスタイルの施設は時代遅れになる傾向があり、常に利用できるとは限りません。 POSIXメッセージキュー機能の使用をお勧めします。 mq_overview(7) を読んでください。

自由にダウンロード可能な Advanced Linux Programming (古い本。より良いものと新しいものを購入できます)を読みたいと思うかもしれません。 /または intro(2)syscalls(2)intro(3) から到達可能なすべてのマニュアルページ。

10

errnoの値を確認する方法:

  1. _#include <errno.h>_にする必要があります。
  2. はい、あなたは間違いなくif(errno == ENOENT) { ... }のようなことを言うことができます、そしてそれはそれをする一般的で推奨される方法です。
  3. 通常、not use errnoを使用して、エラーが発生したことを確認します。関数の戻り値を確認し、戻り値がエラーを示している場合は、errnoをチェックしてエラーの内容を確認します。 (詳細は以下をご覧ください。)
  4. errnoは変数のように見えますが、実際はそうではありません。 if(errno == ENOENT) { ... }のようなことを言っている限り、これは関係ありません。しかし、おそらく_int errno_ptr = &errno;_のようなことをしようとすべきではありません。
  5. perror()strerror()などの関数を使用して、errno値に対応する人間が読み取れるエラー文字列を取得できます。しかし、はい、あなたが得る文字列は一般的に「そのようなファイルやディレクトリはありません」のようなものです。 errno値ENOENTを文字列_"ENOENT"_に変換する良い方法はありません。

#3についてもう少し言います。時々、次のようなことを言うのは魅力的です

_errno = 0;
printf("Hello, world!\n");
if(errno != 0) {
    fprintf(stderr, "printf failed!\n");
}
_

しかし、それをしないでください。代わりに

_errno = 0;
int retval = printf("Hello, world!\n");
if(retval < 0) {
    fprintf(stderr, "printf failed!\n");
}
_

その理由は、その仕事をしている過程のどこかで、printfがエラーを引き起こした何か、errnoを設定したが、printfが回復したかもしれないからです。そのエラーから、正常に完了しました。

保証されているライブラリ関数は非常に少数ですnotエラーがなければerrnoにタッチします(1つの例はatoiかもしれませんが)、一般に、これは何かですあなたは注意する必要があります。

#4についてもう少し言います。 errnoは変数のように見えます。具体的には、グローバル変数のように見えます。しかし、もちろんグローバル変数は悪いです。しかし、errnoはずっと存在しています。それを使用する数千万行のコードがあります。基本的にはまだかなり便利です。それを「修正」するには遅すぎます。そのため、代わりに、カーテンの後ろを覗くと、ほとんどの実装が次のようなことを行うことがわかります。

_extern int __errno_pointer;
#define errno (*__errno_pointer)
_

または

_extern int *__errno_pointer_function();
#define errno (*__errno_function())
_

このようにして、たとえばマルチスレッドコードでもerrnoが適切に動作するように調整できます。

11
Steve Summit

Errno.hを含める

いくつかの例:

// Error codes
#define EPERM        1  /* Operation not permitted */
#define ENOENT       2  /* No such file or directory */
#define ESRCH        3  /* No such process */
#define EINTR        4  /* Interrupted system call */
#define EIO          5  /* I/O error */
#define ENXIO        6  /* No such device or address */
#define E2BIG        7  /* Argument list too long */
#define ENOEXEC      8  /* Exec format error */
#define EBADF        9  /* Bad file number */
#define ECHILD      10  /* No child processes */
#define EAGAIN      11  /* Try again */
#define ENOMEM      12  /* Out of memory */
#define EACCES      13  /* Permission denied */
#define EFAULT      14  /* Bad address */
#define ENOTBLK     15  /* Block device required */
#define EBUSY       16  /* Device or resource busy */
#define EEXIST      17  /* File exists */
#define EXDEV       18  /* Cross-device link */
#define ENODEV      19  /* No such device */
#define ENOTDIR     20  /* Not a directory */
#define EISDIR      21  /* Is a directory */
#define EINVAL      22  /* Invalid argument */
#define ENFILE      23  /* File table overflow */
#define EMFILE      24  /* Too many open files */
#define ENOTTY      25  /* Not a typewriter */
#define ETXTBSY     26  /* Text file busy */
#define EFBIG       27  /* File too large */
#define ENOSPC      28  /* No space left on device */
#define ESPIPE      29  /* Illegal seek */
#define EROFS       30  /* Read-only file system */
#define EMLINK      31  /* Too many links */
#define EPIPE       32  /* Broken pipe */
#define EDOM        33  /* Math argument out of domain of func */
#define ERANGE      34  /* Math result not representable */

実装には、たとえば/usr/include/asm-generic/errno.h

3
P__J__