Han*_*ana 7 c errno system-calls
我正在使用系统调用,如果失败,我需要为不同的errnos做不同的事情.
我需要编写看起来像这样的代码:
int res;
res = systemCall();
if (res == -1)
{
if (errno == ENOMSG)
{
doSomething();
}
else
{
doSomethingElse();
}
}
Run Code Online (Sandbox Code Playgroud)
perror没有帮助,因为它只打印值.
至于strerro - 如果它是我需要的,我不是如何使用它,因为在这里它说实际的字符串与错误不同.从手册页引用:"(例如,如果errnum是EINVAL,则返回的描述将是"Invalid argument")".
我正在使用Linux.系统调用:msgsend和msgrcv(https://linux.die.net/man/2/msgrcv).我不确定你问的C库是什么.
我看到我没有很好地解释自己.
语句if(errno == ENOMSG)是否有效?是否有这样的变量errno?基本上我的问题是:if为了测试errno ,在声明中应该怎么做?
Ste*_*mit 11
如何检查以下值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");
}
Run Code Online (Sandbox Code Playgroud)
但是不要这样做.相反
errno = 0;
int retval = printf("Hello, world!\n");
if(retval < 0) {
fprintf(stderr, "printf failed!\n");
}
Run Code Online (Sandbox Code Playgroud)
原因是,在printf完成其工作的某个过程中,可能已经做了一些导致错误的事情,一些设置errno,但printf可能已从该错误中恢复并继续成功完成.
如果没有错误(我想一个例子可能是),有一些库函数可以保证不会触及errno atoi,但总的来说,这是你必须要小心的.
更多地谈论#4. errno看起来像一个变量,更具体地说,它看起来像一个全局变量.但当然全局变量都很糟糕.但是errno一直存在; 有数以千万计的代码行使用它; 它基本上还很方便; 现在"修理"它已经太晚了.所以,相反,如果你偷看幕后,你会发现大多数实现都是这样的
extern int __errno_pointer;
#define errno (*__errno_pointer)
Run Code Online (Sandbox Code Playgroud)
要么
extern int *__errno_pointer_function();
#define errno (*__errno_function())
Run Code Online (Sandbox Code Playgroud)
通过这种方式,errno即使在多线程代码中,它们也可以安排合理地正常工作.
Bas*_*tch 10
我假设您使用的是Linux,我认为您不直接使用系统调用,而是在syscalls(2)中列出的一些(简单)包装器(来自您的C库).请注意,一些奇怪的系统调用不是由C库包装的(一个众所周知的解包系统调用示例是sigreturn(2),您可能永远不应该使用它).通常C库是GNU glibc,但它可能是musl-libc等.请注意,内核原始系统调用具有与普通C函数不同的调用约定(因此在实践中需要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);
};
};
Run Code Online (Sandbox Code Playgroud)
声明
if (errno == ENOMSG)......有效吗?
是的; 你想errno 在一些系统调用失败后(例如何时siz<0)进行测试.
有这样的变量
errno吗?
不再.请仔细阅读 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).
您可能希望阅读可免费下载的高级Linux编程(一本旧书;您可以购买更好更新的东西)和/或从介绍(2)和系统调用(2)和介绍(3)可以访问的所有手册页.
包括 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 */
Run Code Online (Sandbox Code Playgroud)
您的实现可能有更多的 errno 包含,例如/usr/include/asm-generic/errno.h.