2012-07-10 48 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

相關問題