<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # POSIX,第 1 部分:錯誤處理 > 原文:<https://github.com/angrave/SystemProgramming/wiki/POSIX%2C-Part-1%3A-Error-handling> ## 什么是 POSIX 錯誤處理? 在其他語言中,您可能會看到使用異常實現的錯誤處理。雖然你在技術上可以在 c 中使用它們(你保留一堆非常 try / catch 塊并使用`setjmp`和`longjmp`分別轉到這些塊),但是 C 中的錯誤處理通常是通過 posix 錯誤處理代碼來完成的看起來像這樣。 ```c int ret = some_system_call() if(ret == ERROR_CODE){ switch(errno){ // Do different stuff based on the errno number. } } ``` 在內核中,`goto`的使用被大量用于清理應用程序的不同部分。 **你不應該使用 gotos** 因為它們使代碼更難閱讀。內核中的 getos 是不必要的,所以不要上課。 ## 什么是`errno`以及何時設定? POSIX 定義了一個特殊的整數`errno`,它在系統調用失敗時設置。 `errno`的初始值為零(即沒有錯誤)。當系統調用失敗時,它通常會返回-1 表示錯誤并設置`errno` ## 多線程怎么樣? 每個線程都有自己的`errno`副本。這非常有用;否則一個線程中的錯誤會干擾另一個線程的錯誤狀態。 ## 什么時候`errno`重置為零? 除非你專門將它重置為零,否則它不會!當系統調用成功時,他們執行 _ 而不是 _ 重置`errno`的值。 這意味著如果您知道系統調用失敗(例如,它返回-1),您應該只依賴于 errno 的值。 ## 使用`errno`有什么問題和最佳做法? 當復雜的錯誤處理使用庫調用或系統調用可能會改變`errno`的值時要小心。實際上,將 errno 的值復制到 int 變量更安全: ```c // Unsafe - the first fprintf may change the value of errno before we use it! if (-1 == sem_wait(&s)) { fprintf(stderr, "An error occurred!"); fprintf(stderr, "The error value is %d\n", errno); } // Better, copy the value before making more system and library calls if (-1 == sem_wait(&s)) { int errno_saved = errno; fprintf(stderr, "An error occurred!"); fprintf(stderr, "The error value is %d\n", errno_saved); } ``` 同樣,如果您的信號處理程序進行任何系統或庫調用,那么最好保存 errno 的原始值并在返回之前恢復該值: ```c void handler(int signal) { int errno_saved = errno; // make system calls that might change errno errno = errno_saved; } ``` ## 如何打印出與特定錯誤號相關聯的字符串消息? 使用`strerror`獲取錯誤值的簡短(英文)描述 ```c char *mesg = strerror(errno); fprintf(stderr, "An error occurred (errno=%d): %s", errno, mesg); ``` ## perror 和 strerror 有什么關系? 在之前的頁面中,我們使用 perror 將錯誤打印到標準錯誤。使用`strerror`,我們現在可以編寫`perror`的簡單實現: ```c void perror(char *what) { fprintf(stderr, "%s: %s\n", what, strerror(errno)); } ``` ## 使用 strerror 有什么問題? 不幸的是`strerror`不是線程安全的。換句話說,兩個線程不能同時調用它! 有兩種解決方法:首先,我們可以使用互斥鎖定義臨界區和本地緩沖區。所有調用`strerror`的地方的所有線程都應該使用相同的互斥鎖 ```c pthread_mutex_lock(&m); char *result = strerror(errno); char *message = malloc(strlen(result) + 1); strcpy(message, result); pthread_mutex_unlock(&m); fprintf(stderr, "An error occurred (errno=%d): %s", errno, message); free(message); ``` 或者使用較不便攜但線程安全的`strerror_r` ## 什么是 EINTR? sem_wait 是什么意思?讀?寫? 當信號(例如 SIGCHLD,SIGPIPE,...)傳遞給過程時,某些系統調用可能會中斷。此時系統調用可能會返回而不執行任何操作!例如,字節可能未被讀/寫,信號量等待可能沒有等待。 可以通過檢查返回值以及`errno`是否為 EINTR 來檢測此中斷。在這種情況下,應重試系統調用。通常會看到包含系統調用的以下類型的循環(例如 sem_wait)。 ```c while ((-1 == systemcall(...)) && (errno == EINTR)) { /* repeat! */} ``` 小心寫`== EINTR`,而不是`= EINTR`。 或者,如果結果值需要稍后使用... ```c while ((-1 == (result = systemcall(...))) && (errno == EINTR)) { /* repeat! */} ``` 在 Linux 上,將`read`和`write`調用到本地磁盤通常不會返回 EINTR(而是自動為您重新啟動該功能)。但是,在對應于網絡流 _ 的文件描述符上調用`read`和`write`可以 _ 返回 EINTR。 ## 哪些系統調用可能被中斷并需要包裝? 使用 man 頁面!手冊頁包括可由系統調用設置的錯誤列表(即錯誤值)。經驗法則是“慢”(阻塞)調用(例如,寫入套接字)可能會被中斷,但快速非阻塞調用(例如 pthread_mutex_lock)則不會。 來自 linux 信號 7 手冊頁。 “如果在阻止系統調用或庫函數調用時調用信號處理程序,則: * 信號處理程序返回后,調用自動重啟;要么 * 調用失敗并顯示錯誤 EINTR。發生這兩種行為中的哪一種取決于接口以及是否使用 SA_RESTART 標志建立了信號處理程序(請參閱 sigaction(2))。 UNIX 系統的細節各不相同;下面是 Linux 的詳細信息。 如果對信號處理程序中斷對以下某個接口的阻塞調用,則在使用 SA_RESTART 標志后,如果信號處理程序返回,則將自動重新啟動該調用。否則呼叫將失敗并顯示錯誤 EINTR: * read(2),readv(2),write(2),writev(2)和 ioctl(2)調用“慢”設備。 “慢”設備是 I / O 調用可能無限期阻塞的設備,例如終端,管道或套接字。 (根據此定義,磁盤不是慢速設備。)如果慢速設備上的 I / O 調用在信號處理程序中斷時已經傳輸了某些數據,則該調用將返回成功狀態(通常,傳輸的字節數)。 “ 注意,很容易相信設置'SA_RESTART'標志足以使整個問題消失。不幸的是,這不是真的:仍有系統調用可能提前返回并設置`EINTR`!有關詳細信息,請參見[信號(7)](https://cs-education.github.io/sysassets/man_pages/html/man7/signal.7.html)。 ## Errno 例外嗎? 有些 POSIX 實用程序每個人都有自己的錯誤。一種是當你調用`getaddrinfo`時檢查錯誤并轉換為字符串的函數是 [gai_strerr](https://linux.die.net/man/3/gai_strerror) 。不要混淆他們!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看