多線程中的errno原理詳解/errno的安全執行緒

來源:互聯網
上載者:User

一、errno的由來
     在C編程中,errno是個不可缺少的變數,特別是在網路編程中。如果你沒有用過errno,那隻能說明你的程式不夠健壯。當然,如果你是WIN32平台的GetLastError(),效果也是一樣的。
     為什麼會使用errno呢?個人認為,這是系統庫設計中的一個無奈之舉,他更多的是個技巧,而不是架構上的需要。我們觀察下函數結構,可以發現,函數的參數傳回值只有一個,這個傳回值一般可以攜帶錯誤資訊,比如負數表示錯誤,而正數表述正確的傳回值,比如recv函數。但是對於一些返回指標的函數,如: char *get_str();這個方法顯然沒有用的。NULL可以表示發生錯誤,但是發生什麼錯誤卻毫無辦法。於是,errno就誕生了。全域變數errno可以存放錯誤原因,當錯誤發生時,函數的傳回值是可以通過非法值來提示錯誤的發生。

二、errno的安全執行緒
     errno是全域變數,但是在多線程環境下,就會變得很恐怖。當你調用一個函數時,發現這個函數發生了錯誤,但當你使用錯誤原因時,他卻變成了另外一個線程的錯誤提示。想想就會覺得是件可怕的事情。
     將errno設定為線程局部變數是個不錯的主意,事實上,GCC中就是這麼乾的。他保證了線程之間的錯誤原因不會互相串改,當你在一個線程中串列執行一系列過程,那麼得到的errno仍然是正確的。
    看下,bits/errno.h的定義:
# ifndef __ASSEMBLER__
/* Function to get address of global `errno' variable.  */
extern int *__errno_location (void) __THROW __attribute__ ((__const__));
 #  if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value.  */
#   define errno (*__errno_location ())
#  endif
# endif /* !__ASSEMBLER__ */
     而errno.h中是這樣定義的:
/* Declare the `errno' variable, unless it's defined as a macro by
   bits/errno.h.  This is the case in GNU, where it is a per-thread
   variable.  This redeclaration using the macro still works, but it
   will be a function declaration without a prototype and may trigger
   a -Wstrict-prototypes warning.  */
#ifndef errno
extern int errno;
#endif
     顯然,errno實際上,並不是我們通常認為的是個整型數值,而是通過整型指標來擷取值的。這個整型就是安全執行緒的。


三、errno的實現

static pthread_key_t key;
static pthread_once_t key_once = PTHREAD_ONCE_INIT;
static void make_key()
{
    (void) pthread_key_create(&key, NULL);
}
int *_errno()
{
    int *ptr ;
    (void) pthread_once(&key_once, make_key);
    if ((ptr = pthread_getspecific(key)) == NULL) 
    {
        ptr = malloc(sizeof(int));        
        (void) pthread_setspecific(key, ptr);
    }
    return ptr ;
}

 四、errno的應用
    errno在庫中得到廣泛的應用,但是,錯誤編碼實際上不止那麼多。我們需要在自己的系統中增加更多的錯誤編碼。一種方式就是直接利用errno,另外一種方式就是定義自己的user_errno。
   使用errno,strerror可能無法解析,這需要自己解決。但errno使用線程變數的方式值得借鑒。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.