8

在通常情况下 open(),返回新的文件描述符,如果发生错误,则返回 -1,在这种情况下,errno设置适当。

我不明白为什么errno这里使用这种机制?这里的目的是什么?为什么我们不能用一些负回报来映射所有错误?

喜欢

fd = open("/dev/tty0", O_RDWR | O_SYNC);
if(fd == -1)
  printf("this is EACCES error");
else if (fd == -2)
    printf("this is EPERM error");

有没有errno 机制的好处。?如果是,那么我想知道/理解然后在其他事情上我也可以使用这种机制。

4

4 回答 4

12

由于fopen返回 aFILE*您不能指望它在该指针中返回错误代码:指针的唯一“特殊”值是0.

正如你所观察到的,因为open这个限制不成立。事实上,像 linux 这样的系统完全按照您在较低级别提出的建议。如果出现问题,后台的系统调用会返回负错误代码。errno然后,该(否定的)代码由浅用户空间包装器插入,然后返回-1以向应用程序指示错误。

这样做的原因纯粹是历史原因。在过去的美好时光中,没有线程,errno仍然只是一个简单的全局变量。当时所选择的策略不会产生太多开销,并且可能似乎是操作系统和应用程序之间可以接受的通信方式。由于这样的接口基本上不能在不破坏大量代码的情况下进行更改,因此我们将被困在errno线程本地的伪变量中。

这并不理想,但开销并不像听起来那么糟糕,因为这些显然是错误指示,只应在异常情况下发生。

于 2012-07-10T12:52:47.730 回答
9

对我来说,优势在于以这种方式统一获取错误信息,返回一些负值可以正常工作,open因为它返回一个整数,但fopen返回 aFILE *所以必须在那里使用另一种技术。

于 2012-07-10T12:35:12.673 回答
1

为每个函数提供一组不同的返回值会使以通用方式编写代码变得过于复杂。使用当前语义,您可以采用通用模式:

int fd;
if ((fd = some_function(arg1, arg2)) == -1)
{
    perror("some_function");
    exit(1);
}

您甚至可以将其包装在宏中:

#define CALL_OR_DIE(function, ret, ...)      \
    if ((ret = function(__VA_ARGS__)) == -1) \
    { perror(#function); exit(1); }

用法:

int fd;
CALL_OR_DIE(open, fd, "/dev/tty0", O_RDWR | O_SYNC);
于 2012-07-10T12:49:11.330 回答
1

errno是错误代码。将错误映射到实际发生的情况非常重要,这样您就可以在代码中就下一步做什么做出战略决策。例如,ERANGE在 中定义的errno.h,将告诉您的结果strtol("0xfffffffff",NULL,0)超出了该函数的范围。在您的示例中更重要的是,最好知道您是否有EACCES错误EPERM,以便您知道如何处理文件。

您无法将所有问题都映射到一个错误代码,因为您可能有多个要捕获和处理的问题。当我说 catch 时,我并不是指 try/catch。

errno 的使用建立了错误处理机制,因此您获得的信息不仅仅是-1。

为了方便起见,ERANGE、EACCES、EPERM 和其他被视为映射到特定错误号的宏。

于 2012-07-10T12:34:19.787 回答