如何检查errno的值?
我正在使用系统调用,如果它失败,我需要为不同的errnos做不同的事情。如何检查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,我想,你不直接使用系统调用,但在syscalls(2)一些(简单)包装(从C库)的上市。请注意,一些奇怪的系统调用未被C库包装(一个众所周知的未包装系统调用的示例应该是sigreturn(2),您可能不应该使用它)。 C库通常是GNU glibc,但它可能是musl-libc等。另请注意,内核原始系统调用与普通C函数有不同的calling conventions(因此实际上需要libc包装,并负责处理errno
)。还请注意,errno(3)通常是一个宏(几乎像一些变量一样)。
的msgrcv(2)手册页文档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)
....有效吗?
是的,您只想在某些系统调用失败后(例如siz<0
)测试errno
。
是否有这样一个变量
errno
?
没有更多。请仔细阅读errno(3)文件。你不应该声明extern int errno;
(这是有可能在20世纪80年代,而不是在21 ST世纪),但你应该总是#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)。
高级Linux编程下载链接可能已损坏或已过时。似乎没有为我工作。 –
更正,今天有一些随机链接工作。其实,如果你能负担得起,更好地阅读一本新书。 –
感谢您的领导!我会寻找更新的东西。如果想到任何事情,会很乐意听到建议。 –
包含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 */
你的实现可能有更多的errno包括,例如像/usr/include/asm-generic/errno.h
。
如何检查errno
值:
- 您将需要
#include <errno.h>
。 - 是的,你绝对可以说像
if(errno == ENOENT) { ... }
这样的事情,这是做这件事的常用方法。 - 一般来说,做而不是使用
errno
来确定发生了错误。检查函数的返回值,如果返回值指示错误,则检查errno
以查看错误是什么。 (更多关于下面的内容。) -
errno
看起来像一个变量,但它实际上不是。只要你说出像if(errno == ENOENT) { ... }
这样的东西,这就不关你了。但你可能不应该尝试做类似的事情。 - 您可以使用像
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
可能已经从错误中恢复匆匆上成功完成。
但是也有一些保证不碰错误号,如果没有错误极少数的库函数(我想一个例子可能是atoi
),但总的来说,这是你必须要小心的东西。
再说一点关于#4的内容。errno
看起来像一个变量,更具体地说,它看起来像一个全局变量。但是,当然全球变量是不好的。但是errno
已经存在了,有数千万行代码使用它;它仍然基本上非常方便; “修复”它为时已晚。所以,相反,如果你偷看了幕后,你会发现,大多数实现这样做
extern int __errno_pointer;
#define errno (*__errno_pointer)
或
extern int *__errno_pointer_function();
#define errno (*__errno_function())
通过这种方式,他们可以安排errno
合理正常甚至工作例如,多线程代码。
在什么操作系统上?什么确切的系统调用?什么C库?请**编辑您的问题以改进它** –
每个系统调用都有一个可能的errno值列表(请参阅它的'man'页面),这会让您知道您应该测试什么。 – Myst
你写的很好。请记住,没有库函数将'errno'设置为零,除非函数指示错误并且记录为设置'errno',否则不应该对其进行测试。请注意,许多pthreads函数不会设置“errno”,例如;他们会返回错误号码。此外,即使成功,函数也可以将'errno'设置为非零值。例如,在Solaris上,如果标准输出不是终端,即使'printf()'调用成功,'errno'也可以设置为ENOTTY。 –