• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

            路漫漫,長修遠,我們不能沒有錢
            隨筆 - 173, 文章 - 0, 評論 - 257, 引用 - 0
            數據加載中……

            防止信號處理失靈(轉載)

            ?  防止信號處理失靈
              
               作者:Danny Kalev
               編譯:MTT 工作室
              
               原文出處:Preventing Glitches in Signal Processing
              
              
               摘要:本文將剖析 ANSI <signal.h>庫并示范如何使用其接口。進而討論
               POSIX 信號處理 API。
              
              
               信號處理類似硬件中斷。它們促使某個進程從當前的執行控制流程中跳出,以實現特定的行為,待特定處理完成后,再恢復到中斷點繼續執行。本文將剖析
               ANSI <signal.h>庫并示范如何使用其接口。然后,本文將進而討論
               POSIX 信號處理 API。默認情況下,某些信號導致進程終止。例如,試圖存取進程不擁有的內存將觸發 SIGSEGV
               (“段故障”)信號,這時該信號會終止進程的執行。許多應用程序都有這個問題,這是我們不希望看到的。調試,仿真和事務處理系統必須處理這樣的信號以便讓進程繼續執行。那么我們如何防止這種發生呢?
               答案是安裝一個處理器處理進來的信號并在發生時捕獲它們
              
               第一步:建立信號處理器
              
               信號是內核傳給某個進程的一個整數。當進程接收到信號,它便以以下方式之一響應:
               忽略該信號;
               讓內核完成與該信號關聯的默認操作
               捕獲該信號,即讓內核將控制傳給信號處理例程,等信號處理例程執行完畢,然后又從中斷的地方恢復程序的執行。
              
              
               所謂信號處理例程是一個函數,當某個信號發生時,內核會自動調用該函數。signal()函數為給定的信號注冊一個處理例程:typedef void (*handler)(void);
              void * signal(int signum, handler);
               第一個參數是信號編碼。第二個參數用戶定義的函數地址,當信號 signum 產生時,handler 所指向的函數被調用。
               除了函數地址之外,第二個參數也可以是兩個特殊的值:SIG_IGN 和 SIG_DFL。SIG_IGN 表示該信號應被忽略(注意:SIGKILL
               和 SIGSTOP 在無論如何都是不能被阻塞、捕獲或忽略的);SIG_DFL 指示內核該信號產生時完成默認行為。
              
               第二步:發信號
              
               向某個進程發信號有三種方式:
               進程通過條用 raise() 顯式地發送信號給自己;
               信號從另一個進程發送,比方說通過
               kill() 系統調用或者
               Perl 腳本
               信號從內核發送。例如,當進程試圖存取不屬于自己的內存,或在系統關閉期間存取內存時;
              
               第三步:產生和處理信號
              
               下面程序注冊 SIGTERM 處理器。然后產生一個 SIGTERM 信號,從而導致該處理器運行:
               #include <csignal>
              #include <iostream>
              using namespace std;
              void term(int sig)
              {
              ? //..necessary cleanup operations before terminating
              ? cout << "handling signal no." <<sig <<endl;
              }
              int main()
              {
               signal(SIGTERM, term); // register a SIGTERM handler
               raise(SIGTERM); // will cause term() to run
              }
               ANSI <signal.h> 的局限
               當進入就緒狀態的某個進程準備運行一個 SIGx 信號處理例程時又接收到另一個 SIGx
               信號,這時會發生什么情況呢?一個方法是讓內核中斷該進程并再次運行該信號處理例程。為此,這個處理例程必須是可重入的(re-entrant)。但是,設計可重入的處理例程決非易事。ANSI
               C 解決重現信號(recurring signals)問題的方法是在執行用戶定義的處理例程前,將處理例程重置為 STG_DFL。這樣做是有問題的。
               當兩個信號快速產生時,內核運行第一個信號的處理例程,而對第二個信號則進行默認處理,這樣有可能終止該進程。
               在過去的三十年中出現了幾個可以信號處理框架,每一種框架對重現信號的處理問題提供了不同的解決方法。POSIX 信號 API
               是其中最為成熟的和可移植的一個。
              
               POSIX 信號
               POSIX 信號處理函數操作一組打包在 sigset_t 數據類型中信號:
               int sigemptyset(sigset_t * pset); 清除 pset 中的所有信號。
               int sigfillset(sigset_t * pset); 用可獲得的信號填充 pset。
               int sigaddset(sigset_t * pset, int signum); 將 signum 添加到 pset。
               int sigdelset(sigset_t * pset, int signum); 從 pset 中刪除 signum。
               int sigismember(const sigset_t * pset, int signum); 如果 signum 包含在
               pset 中,則返回非零,否則返回 0。
              
               Sigaction() 為特定的信號注冊處理例程:
               int sigaction(int signum, struct sigaction * act, struct sigaction *prev);
               sigaction 結構描述內核處理 signum 的信息:struct sigaction
              {
              ? sighanlder_t sa_hanlder;
              ? sigset_t sa_mask; // 阻塞信號的清單
              ? unsigned long sa_flags; // 阻塞模式
              ? void (*sa_restorer)(void); // 未使用
              };
               sa_hanlder 保存函數的地址,該函數帶一個整型參數,沒有返回值。它還可以是兩個特別值之一:SIG_DFL 和 SIG_IGN。
              
               額外特性
               POSIX API 提供多種 ANSI 庫中所沒有的服務。其中包括阻塞進入的信號并獲取當前未決信號。
              
              
               阻塞信號
               sigprocmask() 阻塞和取消阻塞信號:int sigprocmask(int mode, const sigset_t* newmask,sigset_t * oldmask);
               mode 可取以下值之一:
               SIG_BLOCK —— 將 newmask 中的信號添加到當前的信號擋板中。
               SIG_UNBLOCK —— 從當前的信號擋板中刪除 newmask 信號。
               SIG_SETMASK —— 僅阻塞 newmask 中的信號。
               獲取未決信號
               阻塞的信號處于等待狀態,直到進程就緒接收它們。這樣的信號被稱為未決信號,可以通過調用 sigpending() 來獲取。
               int sigpending(sigset_t * pset);
              
            作者簡介
               Danny Kalev 是一名通過認證的系統分析師,專攻 C++ 和形式語言理論的軟件工程師。1997 年到 2000
               年期間,他是 C++ 標準委員會成員。最近他以優異成績完成了他在普通語言學研究方面的碩士論文。
               業余時間他喜歡聽古典音樂,閱讀維多利亞時期的文學作品,研究 Hittite、Basque 和 Irish Gaelic
               這樣的自然語言。其它興趣包括考古和地理。Danny 時常到一些 C++ 論壇并定期為不同的 C++
               網站和雜志撰寫文章。他還在教育機構講授程序設計語言和應用語言課程。

            posted on 2006-09-28 09:55 Khan 閱讀(1231) 評論(0)  編輯 收藏 引用 所屬分類: GCC/G++跨平臺開發

            久久久91精品国产一区二区三区 | 国产99久久久国产精免费| 亚洲国产精品综合久久一线| 中文字幕热久久久久久久| 亚洲精品乱码久久久久久蜜桃图片| 欧美一区二区三区久久综合| 欧美一区二区精品久久| 久久99热这里只有精品66| 99精品久久精品一区二区| 久久九九久精品国产| 久久久免费精品re6| 欧美日韩中文字幕久久久不卡| 久久久久久久久无码精品亚洲日韩| 国产精品欧美久久久久天天影视| 狠狠色综合网站久久久久久久高清 | 久久美女人爽女人爽| 人人妻久久人人澡人人爽人人精品| 97超级碰碰碰久久久久| 久久人人爽人人人人爽AV| 99热成人精品免费久久| 久久久久久亚洲AV无码专区| 久久伊人中文无码| 久久久精品一区二区三区| 伊人久久综合成人网| 一级做a爰片久久毛片免费陪 | 色综合久久夜色精品国产| 久久综合丁香激情久久| 国产亚洲精久久久久久无码| 香蕉久久夜色精品升级完成| 香蕉久久夜色精品国产2020| 久久这里只有精品视频99| 亚洲狠狠综合久久| 欧美久久精品一级c片片| 91精品国产高清久久久久久io | 日韩久久久久中文字幕人妻| 国产精品久久久99| 岛国搬运www久久| 国产精品久久久天天影视香蕉 | 国产情侣久久久久aⅴ免费| 久久人人爽人人爽人人片AV不| 精品久久久无码人妻中文字幕|