• <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 閱讀(1227) 評論(0)  編輯 收藏 引用 所屬分類: GCC/G++跨平臺開發

            久久久艹| 国产麻豆精品久久一二三| 亚洲国产精品无码久久SM| 亚洲国产精品久久久久网站| 国产成人久久精品激情| 久久久久人妻精品一区| 久久久久亚洲精品天堂| 久久婷婷五月综合97色一本一本| 综合人妻久久一区二区精品| 色综合久久天天综合| 亚洲国产精品久久久久网站| 9191精品国产免费久久| 久久精品国产影库免费看| 亚洲国产精品热久久| 99久久国产免费福利| 久久久久97国产精华液好用吗| 久久久久国产成人精品亚洲午夜| 丁香五月综合久久激情| 亚洲综合精品香蕉久久网97| 久久99国产精品一区二区| 久久精品成人影院| 热99RE久久精品这里都是精品免费| 国内精品久久久人妻中文字幕| 国产精品无码久久综合| 久久综合综合久久狠狠狠97色88 | 亚洲国产小视频精品久久久三级| 久久综合九色综合欧美就去吻| 免费无码国产欧美久久18| 久久久免费精品re6| 99久久免费只有精品国产| 亚洲精品国产第一综合99久久| 久久精品国产亚洲av高清漫画| 一本大道加勒比久久综合| 青春久久| 99久久免费国产特黄| 久久久久一区二区三区| 青青热久久国产久精品| 久久青草国产手机看片福利盒子 | 日韩久久久久久中文人妻 | 国产精品9999久久久久| 无夜精品久久久久久|