2012-07-10 47 views
9

在通常情况下,open()返回新的文件描述符,如果发生错误则返回-1,在这种情况下,将适当地设置errno为什么fopen()或open()使用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机制的任何中获益,?如果是的话,我想知道/理解,然后在其他事情我也可以使用这种机制。

回答

11

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

如您所见,对于open此限制不适用。事实上,像linux一样,系统完全按照你在低层提出的建议。如果事情出错,引擎盖下的系统调用会返回负面的错误代码。然后,该(否定的)代码通过浅用户空间包装器插入errno,然后该包装器返回-1以向应用程序指示错误。

这样做的原因纯属历史。在古老的时代,没有线程,并且errno仍然只是一个简单的全局变量。那时候所选择的策略没有太多开销,并且可能似乎是OS和应用程序之间进行通信的可接受方式。由于这样的接口基本上不能改变而不会破坏很多代码,所以我们将坚持使用errno作为线程本地的伪变量。

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

+0

+1非常好的答案 – 2012-07-10 12:59:25

1

errno是一个错误代码。将错误映射到实际发生的事情非常重要,因此您可以在代码中做出关于接下来要做什么的战略决策。例如,在errno.h中定义的ERANGE将告诉您,strtol("0xfffffffff",NULL,0)的结果超出了该函数的范围。在你的例子中更重要的是,知道你是否有EACCESEPERM错误是很好的,所以你知道如何处理文件。

您不能映射所有问题与一个错误代码,因为您可能有多个问题,你想赶上和处理。当我说赶上时,我不是指尝试/赶上。

errno的使用建立和错误处理机制,所以你得到更多的信息,而不仅仅是-1。

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

9

对我的优势是得到错误信息,这种方式是统一的,返回一些负值将努力确定与open,因为它返回一个整数,但fopen返回FILE *所以另一种技术将必须在那里使用。

+0

FILE *仍然是指向某个缓冲区/内存的指针,所以永远不会是负数,所以如果发生错误,那么我们不会返回带负值的FILE *吗?因为NULL是0 – 2012-07-10 12:39:14

+6

指针至少在我所知的体系结构中没有符号概念,它可以(理论上)覆盖“底层无符号整数”的整个范围(即32位点可以从0x00000000到0xffffffff) 。 “NULL”只是表示“嘿,这失败了,看看errno,看看出了什么问题” – fvu 2012-07-10 12:42:01

+0

理论上,一组保留指针也可以使用;所需要的只是'char err_ptrs [MAX_ERRNO]; void * EACCESS_ptr = err_ptrs + EACCESS;'等,使EACCESS_ptr成为指针的有效“错误代码”。但是,必须将它们作为整数和指针来复制,以及某些接口使用整个整数空间作为有效返回的事实,仍然使得errno值得。 – 2012-07-10 14:36:11

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); 
+1

所以你基本上说(1)写'== -1'比'<0'更好(errnos被定义为负数),(2)这是'errno'的动机?我认为在故障情况下不需要将'fd'传递给'perror'是有好处的,因为它可以从线程本地的'errno'中读取,但是我不认为它完全解释了为什么errno不是也不会从'open'返回。 – 2012-07-10 12:52:57

相关问题