• <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>

            T9的空間

            You will never walk alone!

              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
              69 隨筆 :: 0 文章 :: 28 評論 :: 0 Trackbacks

            信號
            提供異步時間處理方式
            觸發時機:
            1.終端命令
            2.硬件異常,由kernel拋向對應的Process
            3.kill函數/kill命令(超級用戶or Process的user相同,這里的user id一般是指實際用戶ID or 有效用戶ID,如果支持 _POSIX_SAVED_IDS,那么檢查saved-user-id)
            4.軟件觸發(滿足信號條件)

            這里也稍微解釋下Kill這個東西,kill函數,kill命令并不是字面上殺掉某些東西,kill只是在特定的時間發送信號,
            具體的處理取決于信號本身和信號的處理方式。

            信號的處理方式:
            這個有點類似Java Exception的處理方式,catch住or往上throw

            APUE講的信號處理方式有三種
            1.忽略,SIGKILL/SIGSTOP不能忽略;一般如果Process自己不管的話,應該會走到系統默認的處理流程中,所以不能忽略這件事情是系統自己就會保證的。
            2.捕捉信號,例如SIGCHLD,一般parent會call waitpid取子進程終止狀態,避免他處理Zombie狀態。
            3.執行系統默認動作

            我感覺1和3可以歸為一類吧,只是有些signal沒有系統默認動作,然后就跳過去了。一般的系統默認動作也就是終止進程。

            SIGKILL/SIGSTOP不能被忽略的原因我覺得講的不錯,提供超級用戶終止進程的可靠方法,不然后續有可能進程的行為是未定義的.

            signal函數定義:(

            void (*signal(int signo, void(*func)(int)))(int);

            這個C函數的聲明有點難看懂

            APUE講signal的語義與實現有關,所以建議大家都用sigaction

            不過我看了下Android Bionic下的實現,分別包含BSD以及SYSV的版本,但也都變成了sigaction,所以一般在C庫中就保證了這一點,也就無所謂了。

             

            static __sighandler_t
            _signal(
            int  signum, __sighandler_t  handler, int  flags)
            {
                
            struct sigaction  sa;
                __sighandler_t    result 
            = SIG_ERR;

                sigemptyset( 
            &sa.sa_mask );

                sa.sa_handler 
            = handler;
                sa.sa_flags   
            = flags;

                
            if ( !sigaction( signum, &sa, &sa ) )
                    result 
            = (__sighandler_t) sa.sa_handler;

                
            return result;
            }



            __sighandler_t bsd_signal(
            int signum, __sighandler_t handler)
            {
              
            return _signal(signum, handler, SA_RESTART);
            }


            __sighandler_t sysv_signal(
            int signum, __sighandler_t handler)
            {
              
            return _signal(signum, handler, SA_RESETHAND);
            }



            exec函數會講信號處理方式還原為系統默認,這個應該毫無疑問,exec后地址空間就不一樣了,保留之前的捕捉函數也是無意義的;在這之前是有意義的,我的意思是說fork后exec之前。

            后面有列一大堆是否可以重入的函數,不太想記,然后講到了malloc
            我想不能重入的函數無外乎兩種類型
            one: 自己有maintain一些全局or static變量 --> malloc 維護分配內存時static heap linklist
            two: 函數參數里面有引用之類的,會影響調用者的情況。

            然后我看到這個立馬就想到了線程安全,malloc是線程安全的麼?
            去看了下Bionic的實現,然后就又看到下面這個名字 Dong Lea,馬上就會想到Java Concurrent庫,看到這個你直接就會有想法,Bionic里面這個malloc肯定是線程安全的;
            有時候被這些東西搞的很累,比較煩他,而且Bionic里面用的malloc的那個實現版本(aka dlmalloc)我又沒看懂:(,只好去網上search了一下,有個人做過實驗,有些結論還是可以參考的
            http://www.360doc.com/content/12/0420/23/168576_205320609.shtml

            總的來說,這個東西取決于C庫實現,我想Bionic和Glibc都應該一樣會支持兩種不同的版本,然后編譯的時候就可以確定是否有線程相關操作,然后在link的時候link過來不同的版本

            線程安全和信號安全是兩個概念

            如果在線程安全的malloc中,信號處理函數中發生重入,那么應該是會發生dead lock
            如果是非線程安全中,那么應該是所謂的 undefined behavior.

            前面還有一個概率忘記寫
            早期的Unix系統,如果系統在執行一個低速系統調用(基本可以總結為blocking IO:包括IPC,File IO,ioctl),那么如果捕捉到信號,那么系統就會中斷這個system call -->EINTR, 這在當時是有理由的,而且理由看起來也合理,但是由于user有時候并不知道某些系統調用是否是低速系統調用,BSD引進了自動重啟的功能,linux follow這種規則

            然后有幾個版本的signal函數
            signal默認自動重啟
            _signal(signum, handler, SA_RESTART) 這是由于在sigaction中的flag為SA_RESTART,上面sysV的實現我不想多寫了。
            sigaction也就是可選的了。

            但一般我印象中好多 read/write都是會自己判斷返回值以及errno 是否為 EINTR,然后retry,因為上面這種方式依賴系統實現,需要將所有的signal都設定為SA_RESTART,那么如果有某個信號發生的時候,被他INTR的系統調用才會自動重啟,不知道默認signal在注冊處理行為的時候是不是如此,感覺不太好用。

            alarm函數
            對于很多像alarm這種函數,在設計時or使用時均應該考慮臨界值的問題
            alarm的唯一性,是by process的,process單例
            所以如果alarm兩次,那么第一次會被覆蓋,怎么處理第一次未完成的情況->返回值會帶回來剩余的時間
            怎么取消設定的alarm
            傳入值為0 means cancel
            總之了,這個東西設計的時候還蠻完善的

            后面還有一堆有關signal的標準函數,這里也就不一一列舉

            作業:
            1.去掉for(;;), 那捕捉到SIGUSR1就返回了,pause()只要捕捉到信號,等信號處理完時自己就會返回并帶回EINTR。不曉得為啥有這種題目...
            2.實現sig2str,這有點無聊了.:(不寫
            3.畫runtime stack的樣子。
            4.IO操作的超時最好不要采用alarm的方式,各種原子問題,select/poll是最好的選擇。
            后面有好一些是要寫代碼的...
            我略想,然后就不太愿意寫了.
            PS:有些東西略難...我也是有點想不清楚的樣子,打算慢慢搞。

            后面決定把標題改一下,順利看完書吧...Orz.

            posted on 2013-06-02 21:52 Torres 閱讀(257) 評論(0)  編輯 收藏 引用 所屬分類: APUE
            国产精品久久久福利| 久久99久久99精品免视看动漫| 久久综合亚洲色一区二区三区| 久久精品亚洲乱码伦伦中文| 久久久久久久99精品免费观看| 成人妇女免费播放久久久| 久久99精品免费一区二区| 久久久亚洲AV波多野结衣| 久久精品中文无码资源站| 久久亚洲精品无码观看不卡| 国产成人精品久久免费动漫| 狠狠久久综合伊人不卡| 久久SE精品一区二区| 国产精品免费久久久久久久久| 性欧美丰满熟妇XXXX性久久久 | 污污内射久久一区二区欧美日韩| 亚洲伊人久久综合影院| 久久亚洲精品中文字幕| 77777亚洲午夜久久多喷| 久久久久亚洲AV无码专区网站 | 国产福利电影一区二区三区久久久久成人精品综合 | 伊人久久大香线蕉无码麻豆| 久久久青草久久久青草| 欧美一区二区三区久久综| 性高湖久久久久久久久AAAAA| 久久九九亚洲精品| 99精品国产综合久久久久五月天 | 伊人久久大香线蕉av不卡| 国产精品美女久久久免费| 国产三级久久久精品麻豆三级 | 国产成人香蕉久久久久| 久久久久久午夜成人影院| 伊人色综合久久天天人手人婷 | 色偷偷偷久久伊人大杳蕉| 无码任你躁久久久久久| 久久久久国产精品嫩草影院| 欧美伊香蕉久久综合类网站| 久久精品无码一区二区三区| 天天爽天天爽天天片a久久网| 麻豆亚洲AV永久无码精品久久| 一本久久a久久精品亚洲|