私はシステムコールを使用していますが、失敗した場合は、異なる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
ステートメントに何を入れるべきですか?
私はあなたがLinuxを使用していると仮定し、直接システムコールを使用しないと仮定しますが、いくつかの(単純な)ラッパー( Cライブラリ) syscalls(2) にリストされています。いくつかの奇妙なシステムコールはCライブラリによってラップされないことに注意してください(ラップされていないシステムコールのよく知られた例は sigreturn(2) で、おそらく決して使用すべきではありません)。多くの場合、Cライブラリは GNU glibc ですが、 musl-libc などになる可能性があります。また、カーネルrawシステムコールは異なる 呼び出し規約 であることに注意してください。通常のC関数よりも(したがって、実際にはlibcラッパーが必要であり、errno
の処理を担当します)。また、 errno(3) は一般にマクロであることに注意してください(ほとんど変数として動作します)。
msgrcv(2) manページには、errno
が_E2BIG
_、EACCES
、EFAULT
... 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) から到達可能なすべてのマニュアルページ。
errno
の値を確認する方法:
#include <errno.h>
_にする必要があります。if(errno == ENOENT) { ... }
のようなことを言うことができます、そしてそれはそれをする一般的で推奨される方法です。errno
を使用して、エラーが発生したことを確認します。関数の戻り値を確認し、戻り値がエラーを示している場合は、errno
をチェックしてエラーの内容を確認します。 (詳細は以下をご覧ください。)errno
は変数のように見えますが、実際はそうではありません。 if(errno == ENOENT) { ... }
のようなことを言っている限り、これは関係ありません。しかし、おそらく_int errno_ptr = &errno;
_のようなことをしようとすべきではありません。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
が適切に動作するように調整できます。
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
。