我正在使用系统调用,如果失败,我需要为不同的errnos做不同的事情 .
我需要编写看起来像这样的代码:
int res;
res = systemCall();
if (res == -1)
{
if (errno == ENOMSG)
{
doSomething();
}
else
{
doSomethingElse();
}
}
perror没有帮助,因为它只打印值 .
至于strerro - 如果它是我需要的,我不是如何使用它,因为here它说实际字符串与错误不同 . 从手册页引用:"(For example, if errnum is EINVAL, the returned description will be "无效参数")" .
我正在使用Linux . 系统调用:msgsend和msgrcv(https://linux.die.net/man/2/msgrcv) . 我不确定你问的C库是什么 .
我看到我没有很好地解释自己 .
语句if(errno == ENOMSG)是否有效?是否有这样的变量errno?基本上我的问题是:为了测试errno,应该在 if
语句中进行什么?
3 回答
我假设您使用的是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
...之一(请参阅该手册页以获取所有可能错误的列表) .所以你会编写类似的东西
是的;您希望仅在某些系统调用失败后测试
errno
(例如,当siz<0
时) .不再 . 请仔细阅读errno(3)文档 . 你不应该声明
extern int errno;
(这在20世纪80年代是可能的,而不是在21世纪)但是你应该总是#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
值对应的人类可读错误字符串 . 但是,是的,你得到的字符串通常是"No such file or directory" . 我知道没有好办法将errno值ENOENT
转换为字符串"ENOENT"
.更多地谈论#3 . 有时候说出类似的东西很诱人
但是不要这样做 . 相反
原因是,在完成其工作的某个地方,
printf
可能已经做了导致错误的事情,设置了errno
,但printf
可能已从该错误中恢复并继续成功完成 .如果没有错误(我认为一个例子可能是
atoi
),有一些库函数可以保证不会触及errno,但总的来说,这是你必须要小心的 .更多地谈论#4 .
errno
看起来像一个变量,更具体地说,它看起来像一个全局变量 . 但当然全局变量都很糟糕 . 但是errno
已经永远存在;有数以千万计的代码行使用它;它__649736_太迟了"fix"它 . 所以与其,如果你偷看幕后,你会发现大多数实现都是这样的要么
通过这种方式,即使在多线程代码中,他们也可以安排
errno
合理地正常工作 .包括errno.h
一些例子:
您的实现可能包含更多错误,例如
/usr/include/asm-generic/errno.h
.