如何检查errno的值? [英] How to check the value of errno?

查看:74
本文介绍了如何检查errno的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用系统调用,如果它失败,我需要为不同的 errnos 做不同的事情.

我需要编写如下所示的代码:

int res;res = systemCall();如果 (res == -1){如果(错误号 == ENOMSG){做点什么();}别的{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 库包装(一个众所周知的未包装系统调用的例子是 sigreturn(2) 您可能永远不应该使用).C 库通常是 GNU glibc,但也可能是 musl-libc 等等.还要注意内核原始系统调用有不同的调用约定比普通的C函数(所以实际上需要一个libc包装器,负责处理errno).另请注意,errno(3) 通常是一个宏(几乎表现为某种变量).

msgrcv(2) 手册页文档说明 errno 可以是 E2BIGEACCESEFAULT ... ENOMSGENOSYS ...(请参阅该手册页以获取所有可能错误的列表).

所以你会编写类​​似的代码

ssize_t siz = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);if (siz<0) {//msgrcv 失败并设置了 errno如果(错误号 == ENOMSG)做点什么();否则如果(错误号 == EAGAIN)做别的事情();///等等别的 {syslog(LOG_DAEMON|LOG_ERR, "msgrcv 失败,%s\n",strerror(errno));退出(EXIT_FAILURE);};};

<块引用>

语句 if (errno == ENOMSG) .... 是否有效?

是的;您只想在某些系统调用失败后(例如,当 siz<0 时)测试 errno.

<块引用>

有没有这样的变量errno?

没有了.请仔细阅读errno(3) 文档.你不应该声明 extern int errno;(这在 1980 年代是可能的,而不是在 21st 世纪),但你应该总是 #include <errno.h> 并使用 errno 就好像它是一个变量一样,但它几乎总是一些宏(其定义出现在 /usr/include/bits/errno.h 包含在 /usr/include/errno.h 中.

顺便说一句,SysV 风格的工具往往会过时并且并不总是可用.我推荐使用 POSIX 消息队列工具,阅读 mq_overview(7).

您可能想阅读可免费下载的高级 Linux 编程(一本旧书;您可以购买更好和更新的东西)和/或可从 intro(2) &系统调用(2) &介绍(3).

I am using a system call and in case it fails, I need to do different things for different errnos.

I need to write code that looks something like this:

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

perror doesn't help, because it only prints the value.

As for strerro - if it is what I need, I am not suer how to use it, because here it says that the actual string is not the same as the error. Quote from the man page: "(For example, if errnum is EINVAL, the returned description will be "Invalid argument")".

I am using Linux. System calls: msgsend and msgrcv (https://linux.die.net/man/2/msgrcv). I am not sure what C libraries you are asking about.

I see I didn't explain myself well.

Is the statement if (errno == ENOMSG) valid? Is there such a variable errno? Basically my question is: What should go in the if statement in order to test the errno?

解决方案

I assume you are using Linux, and I suppose that you don't directly use the system call, but some of the (simple) wrappers (from your C library) listed in syscalls(2). Notice that some weird system calls are not wrapped by the C library (a well known example of unwrapped system call would be sigreturn(2) which you probably should never use). Quite often the C library is GNU glibc, but it might be musl-libc etc. Notice also that kernel raw system calls have different calling conventions than ordinary C function (so in practice a libc wrapper is required, and is in charge of dealing with errno). Notice also that errno(3) is generally a macro (almost behaving as some variable).

The msgrcv(2) man page documents that errno could be one of E2BIG, EACCES , EFAULT ... ENOMSG, ENOSYS ... (refer to that man page to get the list of all possible errors).

So you would code something like

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); 
  };
};

Is the statement if (errno == ENOMSG) .... valid?

Yes it is; you want to test errno only after some system call failure (e.g. when siz<0).

Is there such a variable errno?

Not any more. Please read carefully errno(3) documentation. You should not declare extern int errno; (this was possible in the 1980s, not in 21st century) but you should always #include <errno.h> and use errno as if it was a variable, but it is almost always some macro (whose definition appears in /usr/include/bits/errno.h which is included by /usr/include/errno.h).

BTW, SysV-style facilities tend to become obsolete and are not always available. I recommend using POSIX message queues facilities, read mq_overview(7).

You might want to read the freely downloadable Advanced Linux Programming (an old book; you can buy something better & newer) and/or all the man pages reachable from intro(2) & syscalls(2) & intro(3).

这篇关于如何检查errno的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆