青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

桃源谷

心靈的旅行

人生就是一場旅行,不在乎旅行的目的地,在乎的是沿途的風景和看風景的心情 !
posts - 32, comments - 42, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
From 2008精選

UNIXC++程序設(shè)計守則 (2)
原文地址:http://d.hatena.ne.jp/yupo5656/20040712/p2

準則2: 要知道信號處理函數(shù)中可以做那些處理
· 在用sigaction函數(shù)登記的信號處理函數(shù)中可以做的處理是被嚴格限定的
· 僅僅允許做下面的三種處理
   1. 局部變量的相關(guān)處理
   2. “volatile sig_atomic_t”類型的全局變量的相關(guān)操作
   3. 調(diào)用異步信號安全的相關(guān)函數(shù)
· 以外的其他處理不要做

 
說明
因為在收到信號時要做一些處理,那通常是準備一個信號處理函數(shù)并用sigaction函數(shù)把它和信號名進行關(guān)聯(lián)的話就OK了。但是,在這個信號處理函數(shù)里可以做的處理是像上面那樣被嚴格限定的。沒有很好掌握這些知識就隨便寫一些代碼的話就會引起下面那樣的問題
· 問題1: 有程序死鎖的危險
   o  這是那些依賴于某一時刻,而且錯誤再現(xiàn)比較困難的BUG產(chǎn)生的真正原因
   o  死鎖是一個比較典型的例子,除此之外還能引起函數(shù)返回值不正確,以及在某一函數(shù)內(nèi)執(zhí)行時突然收到SEGV信號等的誤操作。
   譯者注1SEGV通常發(fā)生在試圖訪問無效內(nèi)存區(qū)域(可能是個NULL,或超出程空之外的內(nèi)存地址)。當bug原因和SEGV影響在不同時間現(xiàn)時,它別難于捕到。


· 問題2: 由于編譯器無意識的優(yōu)化操作,有導致程序紊亂的危險
   o  這是跟編譯器以及編譯器優(yōu)化級別有關(guān)系的bug。它也是“編譯器做了優(yōu)化處理而不能正常動作”,“因為inline化了程序不能動作了”,“變換了OS了程序也不能動作”等這些解析困難bug產(chǎn)生的原因。

 
還是一邊看具體的代碼一邊解說吧。在下面的代碼里至少有三個問題,根據(jù)環(huán)境的不同很可能引起不正確的動作*1按照次序來說明里面的錯誤

 

 1int gSignaled;
 2void sig_handler(int signo) {
 3    std::printf("signal %d received!\n", signo);
 4    gSignaled = 1;
 5}

 6int main(void{
 7    struct sigaction sa;
 8  // (省略)
 9  sigaction(SIGINT, &sa, 0);
10    gSignaled = 0;
11    while(!gSignaled) {
12  //std::printf("waiting\n");
13        struct timespec t = 10 }; nanosleep(&t, 0);
14    }

15}

16

 

錯誤1: 競爭條件
    在上面的代碼里有競爭條件sigaction函數(shù)被調(diào)用后gSignaled還未被賦值成0值之前,如果接受到SIGINT信號了那會變得怎么樣呢? 在信號處理函數(shù)中被覆寫成1后的gSignaled會在信號處理函數(shù)返回后被初始化成0在后面的while循環(huán)里可能會變成死循環(huán)


錯誤2: 全局變量gSignaled 聲明的類型不正確
     在信號處理函數(shù)里使用的全局變數(shù)gSignaled的類型沒有聲明成volatile sig_atomic_t 這樣的話在執(zhí)行while循環(huán)里的代碼的時候接收到了了SIGINT信號時有可能引起while的死循環(huán)那為什么能引起這樣的情況呢
    · 信號處理函數(shù)里,把內(nèi)存上gSignaled的值變更成1 ,它的匯編代碼如下:

 

          movl    $1, gSignaled

    · 但是,就像下面的代碼描述的那樣,main函數(shù)是把gSignaled的值存放到了寄存器里while循環(huán)之前,僅僅是做了一次拷貝變量gSignaled內(nèi)存上的值到寄存器里而在while循環(huán)里只是參照這個寄存器里的值
          movl     gSignaled, %ebx
       .L8:
                       testl    %ebx, %ebx
                       jne      .L8

     在不執(zhí)行優(yōu)化的情況下編譯后編譯器有可能不會生成上面那樣的偽代碼Gcc當使用-O2選項做優(yōu)化編譯時,生成的實際那樣的匯編代碼產(chǎn)生的危害并不僅僅是像上面說的威脅那樣簡單。這方面的問題,是設(shè)備驅(qū)動的開發(fā)者所要知道的常識,但現(xiàn)實情況是對于應用程序的設(shè)計者.開發(fā)者幾乎都不知道這些知識。
為了解決上面的問題,全局變量gSignaled的類型要像下面那樣聲明

     volatile sig_atomic_t gSignaled;

     volatile則是提示編譯器不要像上面那樣做優(yōu)化處理,變成每次循環(huán)都要參照該變量內(nèi)存里的值那樣進行編譯。所以在信號處理函數(shù)里把該變量的值修改后也能真實反映到main函數(shù)的while循環(huán)里
sig_atomic_t 是根據(jù)CPU類型使用typedef來適當定義的整數(shù)值,例如x86平臺是int就是指用一條機器指令來更新內(nèi)存里的最大數(shù)據(jù)*2在信號處理函數(shù)里要被引用的變量必須要定義成sig_atomic_t類型那么不是sig_atomic_t類型的變量(比如x86平臺上的64位整數(shù))就得使用兩條機器指令來完成更新動作。如果在執(zhí)行一條機器指令的時候突然收到一個信號而程序執(zhí)行被中斷,而且在信號處理函數(shù)中一引用這個變量的話,就只能看到這個變量的部分的值。另外,由于字節(jié)對齊的問題不能由一條機器指令來完成的情況也會存在。把該變量的類型變成sig_atomic_t的話,這個變量被更新時就只需要一條機器指令就可以完成了。所以在信號處理函數(shù)里即使使用了該變量也不會出現(xiàn)任何問題

     2006/1/16 補充: 有一點東西忘記寫了關(guān)于sig_atomic_t詳細的東西,請參考C99規(guī)范的§7.14.1.1/5小節(jié)在信號處理函數(shù)里對volatile sig_atomic_t以外的變量進行修改,其結(jié)果都是"unspecified"(參照譯者注2)另外, sig_atomic_t類型的變量的取值范圍是在SIG_ATOMIC_MIN/MAX之間 (參見§7.18.3/2)有無符號是跟具體的實現(xiàn)有關(guān)。考慮到移植性取值在0127之間是比較合適的C99也支持這個取值范圍C++規(guī)范(14882:2003)里也有同樣的描述確切的位置是§1.9/9這里SUSv3的相關(guān)描述請參考sigaction這里*3此外雖然在GCC的參考手冊里也說了把指針類型更新成原子操作,但在標準C/C++卻沒有記載*4
譯者注2
           When the processing of the abstract machine is interrupted by receipt of a signal, the value of objects with type other than volatile sig_atomic_t are unspecified, and the value of any object not of volatile sig_atomic_t that is modified by the handler becomes undefined.
                       ------
ISO/IEC FDIS 14882:1998(E) 1.9小節(jié)


錯誤3: 在信號處理函數(shù)里調(diào)用了不可重入的函數(shù)
上述的樣例代碼中調(diào)用了printf函數(shù),但是這個函數(shù)是一個不可重入函數(shù),所以在信號處理函數(shù)里調(diào)用的話可能會引起問題。具體的是,在信號處理函數(shù)里調(diào)用printf函數(shù)的瞬間,引起程序死鎖的可能性還是有的。但是,這個問題跟具體的時機有關(guān)系,所以再現(xiàn)起來很困難,也就成了一個很難解決的bug了。
下面講一下bug發(fā)生的過程。首先講解一下printf函數(shù)的內(nèi)部實現(xiàn)。
    · printf函數(shù)內(nèi)部調(diào)用malloc函數(shù)
    · malloc函數(shù)會在內(nèi)部維護一個靜態(tài)區(qū)域來保存mutex是為了在多線程調(diào)用malloc函數(shù)的時候起到互斥的作用
    · 總之malloc函數(shù)里有“mutex鎖定,分配內(nèi)存,mutex解鎖”這樣“連續(xù)的不能被中斷”的處理

 

main関數(shù):
  call printf  // while循環(huán)中的printf函數(shù)
    call malloc
      call pthread_mutex_lock(鎖定malloc函數(shù)內(nèi)的靜態(tài)
mutex)
      // malloc處理時
..
收到SIGINT信號

        call sig_handler
          call printf // 信號處理函數(shù)中的printf函數(shù)

            call malloc
              call pthread_mutex_lock(鎖定malloc函數(shù)內(nèi)的靜態(tài)
mutex)
              // 相同的mutex一被再度鎖定,就死鎖啦!!

 
     知道上面的流程的話像這樣的由于信號中斷引起的死鎖就能被理解了吧。為了修正這個bug,在信號處理函數(shù)里就必須調(diào)用可重入函數(shù)。可重入函數(shù)的一覽表在UNIX規(guī)范 (SUSv3)有詳細記載*5你一定會驚訝于這個表里的函數(shù)少吧。
另外,一定不要忘記以下的幾點:
    · 雖然在SUSv3里有異步信號安全(async-signal-safe)函數(shù)的一覽,但根據(jù)不同的操作系統(tǒng),某些函數(shù)是沒有被實現(xiàn)的。所以一定要參考操作系統(tǒng)的手冊
    · 第三者做成的函數(shù),如果沒有特別說明的場合,首先要假定這個函數(shù)是不可重入函數(shù),不能隨便在信  號處理函數(shù)中使用。
    · 調(diào)用不可重入函數(shù)的那些函數(shù)就會變成不可重入函數(shù)了


    最后,為了明確起見,想說明一下什么是異步信號安全(async-signal-safe)”函數(shù)異步信號安全函數(shù)是指在該函數(shù)內(nèi)部即使因為信號而正在被中斷,在其他的地方該函數(shù)再被調(diào)用了也沒有任何問題。如果函數(shù)中存在更新靜態(tài)區(qū)域里的數(shù)據(jù)的情況(例如,malloc),一般情況下都是不全的異步信號函數(shù)。但是,即使使用靜態(tài)數(shù)據(jù),如果在這里這個數(shù)據(jù)時候把信號屏蔽了的話,它就會變成異步信號安全函數(shù)了。
譯者注3:不可重入函數(shù)就不是異步信號安全函數(shù)

 


*1sigaction函數(shù)被調(diào)用前,一接收到SIGINT信號就終止程序,暫且除外吧
*2“最大”是不完全正確的例如,Alpha平臺上32/64bit的變量用一條命令也能被更新,但是好像把8/16bit的數(shù)據(jù)更新編程了多條命令了http://lists.sourceforge.jp/mailman/archives/anthy-dev/2005-September/002336.html 請參考這個URL地址
*3If the signal occurs other than as the result of calling abort(), kill(), or raise(), the behavior is undefined if the signal handler calls any function in the standard library other than one of the functions listed in the table above or refers to any object with static storage duration other than by assigning a value to a static storage duration variable of type volatile sig_atomic_t. Furthermore, if such a call fails, the value of errno is unspecified.
*4在這個手冊里“ In practice, you can assume that int and other integer types no longer than int are atomic. ”這部分是不正確的請參照Alpha的例子
*5The following table defines a set of functions that shall be either reentrant or non-interruptible by signals and shall be async-signal-safe. 后面有異步信號安全函數(shù)一覽

我的個人簡歷第一頁 我的個人簡歷第二頁
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲精品欧美在线| 欧美国产激情| 在线观看日韩精品| 国产偷自视频区视频一区二区| 欧美国产综合| 欧美r片在线| 欧美日韩国产综合久久| 欧美日韩综合在线| 国产精品久久9| 国内伊人久久久久久网站视频| 黄色免费成人| 亚洲精品系列| 亚洲你懂的在线视频| 香蕉久久精品日日躁夜夜躁| 亚洲精品乱码久久久久久黑人 | 欧美精品国产精品| 欧美日韩国产一级片| 国产精品乱看| 国内精品久久久久久影视8| 国产一区二区你懂的| 亚洲人成在线观看一区二区| 亚洲免费一在线| 久久亚洲综合网| 亚洲精品乱码久久久久久黑人| 亚洲国产精品悠悠久久琪琪| 一区二区三区高清在线观看| 亚久久调教视频| 免费美女久久99| 国产精品视频大全| 亚洲国产一二三| 欧美一级二区| 亚洲精品在线三区| 久久国产精品高清| 欧美精品激情| 亚洲电影在线看| 午夜视频在线观看一区| 免费久久99精品国产| 一区二区av在线| 老巨人导航500精品| 国产精品手机视频| 一区二区三区免费网站| 亚洲成在人线av| 国产精品久久久久影院亚瑟| 国产美女一区二区| 99精品视频一区| 蜜桃av一区二区| 亚洲欧美国产日韩天堂区| 鲁大师成人一区二区三区| 国产欧美日韩视频在线观看| 中文在线一区| 亚洲精品国产品国语在线app | 亚洲国产精品一区二区第一页| 欧美在线播放视频| 国产精品一区二区a| 亚洲一区二区三区在线视频| 欧美激情一区二区三区成人| 欧美与黑人午夜性猛交久久久| 国产精品久久中文| 亚洲一区二区三区在线播放| 9l国产精品久久久久麻豆| 欧美日本成人| 99国产精品久久久| 日韩视频不卡| 欧美午夜激情小视频| 在线一区亚洲| 亚洲第一久久影院| 国产视频一区免费看| 亚洲欧美在线播放| 亚洲一级二级在线| 国产欧美亚洲一区| 久久久久网址| 久久精精品视频| 在线播放亚洲一区| 欧美插天视频在线播放| 久久综合久色欧美综合狠狠 | 亚洲精品1区2区| 久久久久久久一区二区| 激情欧美一区| 亚洲国产片色| 国产精品久久久久久久久久免费看| 亚洲嫩草精品久久| 久久xxxx| 亚洲欧洲视频| 99视频有精品| 国产午夜精品视频| 亚洲电影在线| 国产乱子伦一区二区三区国色天香| 午夜久久久久| 快she精品国产999| 亚洲一级黄色片| 久久国产天堂福利天堂| 亚洲国产欧美一区二区三区久久| 奶水喷射视频一区| 欧美三日本三级三级在线播放| 久久国产精品久久久久久久久久 | 久久精品免费播放| 亚洲毛片一区二区| 午夜一区在线| 9久草视频在线视频精品| 亚洲综合色噜噜狠狠| 亚洲黄网站在线观看| 亚洲性线免费观看视频成熟| 最新国产乱人伦偷精品免费网站| 一区二区三区日韩欧美| 亚洲高清在线精品| 亚洲伊人伊色伊影伊综合网 | 亚洲精品久久久久久下一站| 亚洲亚洲精品在线观看 | 欧美成人亚洲成人日韩成人| 欧美午夜免费电影| 亚洲第一精品影视| 国产一区二区高清| 亚洲午夜91| 亚洲最新视频在线| 久久尤物视频| 久久久欧美一区二区| 欧美激情一区| 伊人婷婷欧美激情| 亚洲欧美日韩一区二区| 久久综合狠狠| 久久精品一区二区三区不卡牛牛 | 国产精品极品美女粉嫩高清在线| 免费观看成人网| 国产精品一区二区三区久久| 日韩午夜在线电影| 日韩一级精品视频在线观看| 久久日韩粉嫩一区二区三区| 欧美在线免费一级片| 欧美日韩亚洲一区二区三区四区| 欧美激情欧美激情在线五月| 黑人巨大精品欧美黑白配亚洲| 亚洲欧美日韩天堂一区二区| 一区二区三区视频在线| 欧美人交a欧美精品| 最新高清无码专区| 亚洲剧情一区二区| 欧美成人自拍| 最新成人av网站| 中国成人黄色视屏| 国产精品福利久久久| 在线综合视频| 欧美一区二区三区在线观看视频| 国产精品麻豆成人av电影艾秋| 中国女人久久久| 欧美亚洲视频一区二区| 国产日韩欧美在线一区| 欧美专区亚洲专区| 你懂的一区二区| 亚洲乱码国产乱码精品精天堂| 欧美精品日韩精品| 亚洲无线视频| 久久综合九色| 亚洲精品资源| 国产精品免费网站在线观看| 午夜精品久久久久久99热| 玖玖在线精品| 日韩视频在线免费观看| 国产精品a久久久久久| 欧美一级午夜免费电影| 免费看av成人| 在线视频日本亚洲性| 国产精品中文字幕在线观看| 久久久久久夜| av不卡在线看| 久久九九精品| av成人毛片| 激情欧美国产欧美| 欧美日韩免费看| 久久国产视频网| 亚洲另类一区二区| 久久久久久黄| 中国av一区| 亚洲国产欧美日韩| 国产老肥熟一区二区三区| 久久一区亚洲| 亚洲一区二区三区涩| 亚洲国产99精品国自产| 性欧美激情精品| 亚洲区欧美区| 国产一区二区三区久久久久久久久 | 欧美精品日韩www.p站| 亚洲黄一区二区三区| 欧美日韩一区二区三区四区在线观看 | 亚洲人成网站在线观看播放| 国产精品白丝黑袜喷水久久久| 午夜免费电影一区在线观看 | 亚洲欧美日韩爽爽影院| 亚洲人体1000| 久久综合给合久久狠狠狠97色69| 亚洲精品欧美日韩专区| 国内成人精品2018免费看 | 欧美性大战xxxxx久久久| 久久久一区二区| 亚洲一区国产视频| 亚洲美女在线国产| 欧美黄在线观看| 美女视频一区免费观看| 欧美在线视频观看| 亚洲免费一在线| 亚洲男人天堂2024|