日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

理解信號(進程篇)

 mzsm 2015-09-16
作者:新浪微博(@NP等不等于P

計算機學習微信公眾號(jsj_xx)

信號就是軟件中斷,和硬件中斷有很多類似之處。本文分享我們對信號這種異步事件處理的理解,僅考慮進程,不涉及多線程(如有錯誤,還請指正,謝謝)。

【參考linux kernel source code 4.0,syscall rt_sigaction()、send_signal()、do_signal()

1 不可靠信號

由于信號歷史悠久,我們還得從不可靠信號講起。

不可靠的根因在于存在競態(tài)時間窗口,畢竟異步就難以預(yù)測發(fā)生信號的時機。早期信號的問題有:

  • 每個信號僅期望觸發(fā)一次。觸發(fā)完內(nèi)核立即將信號處理函數(shù)重置為默認值,這樣自定義處理必須手動恢復(fù),從而在自定義信號處理里、但是在恢復(fù)這個動作前,會有一個競態(tài)窗口。

  • 有時阻止不了信號。由于缺少信號掩碼操作,導(dǎo)致在pause()前可能發(fā)生信號,由于這個競態(tài)窗口的存在從而導(dǎo)致pause可能再也等不到信號。

對于pause問題,setjmp是一個治標不治本的解決方案。因為它的暴力跳轉(zhuǎn)會讓其它的信號處理夭折,并且還不能解決好信號掩碼的在遷移時的保護和恢復(fù)。

可見,這些競態(tài)窗口的存在,就是早期信號不可靠的根因??煽啃盘柕囊粋€目的,就是要消滅掉這些競態(tài)窗口。

2 可靠信號

我們(計算機學習微信公眾號:jsj_xx)的理解是:sigprocmask/sigpending/sigsetjmp/siglongjmp/sigsuspend,這些函數(shù)存在的意義就是要解決上文中提到的競態(tài)窗口問題的!

我們逐個分析:

  • 對于sigprocmask和sigpending,質(zhì)樸的(原始的)解決方式。

    最細粒度地解決競態(tài)窗口。

  • sigsuspend相當于sigprocmask和pause的合成,提供設(shè)置信號掩碼后等待的一個原子操作。

    一個基于sigprocmask的具體應(yīng)用(擴展)。一個原子的智能化(手動設(shè)置自定義掩碼和自動恢復(fù)老掩碼)操作。不能提供sigprocmask和其它慢速系統(tǒng)調(diào)用的合成,很遺憾。

  • siglongsetjmp和siglongjmp,則是setjmp和longjmp的信號版本,提供跳轉(zhuǎn)時的信號掩碼現(xiàn)場的保護和恢復(fù)。

    然而,跳轉(zhuǎn)方式依舊是一個指標不治本的方案。

可見,對于等待一個全局變量(全局變量在一個信號處理中設(shè)置)這樣一個處理,總算有了完美方案:sigsuspend。結(jié)合sigaction函數(shù),我們是這么理解的:

  • sigprocmask在信號處理外部實施指定的屏蔽(掩碼)操作。

  • sigaction函數(shù)在信號處理內(nèi)部實施指定的屏蔽(同一信號不可重入)操作。

這樣,內(nèi)外結(jié)合,自然擁有完全的可靠性。

3 兼容方案

基于sigaction函數(shù),其中也支持對早期不可靠信號的支持:

  • SA_NODEFER

    讓信號采用早期的不自動屏蔽的行為。

  • SA_RESETHAND

    讓信號采用早期的自動重置默認處理的行為。

  • SA_RESTART

    此信號要讓系統(tǒng)調(diào)用重啟(當然也需要系統(tǒng)調(diào)用的支持,像read/write/wait等慢速系統(tǒng)調(diào)用都是支持重啟的)。

  • SA_INTERRUPT

    此信號不要讓系統(tǒng)調(diào)用重啟。

可見,調(diào)用sigaction時指定SA_RESETHAND(參考代碼,同SA_ONESHOT)和SA_NODEFER(參考代碼,同SA_NOMASK)就可以完美實現(xiàn)早期的信號方式了。關(guān)于重啟系統(tǒng)調(diào)用,注意SIGALRM的處理:一定不能設(shè)置為SA_RESTART方式,或者更苛刻(安全)的,需要設(shè)置為SA_INTERRUPT方式。

4 信號可重入

早期的信號處理中重置默認處理的行為,可以看作是在變通解決重入問題(當然,現(xiàn)在已經(jīng)通過自動掩碼使得同一信號處理不可重入了)。信號處理里要保證調(diào)用異步信號安全的函數(shù)。這是顯然的,畢竟信號是異步處理。需要注意的是,多線程里即使信號處理中使用異步信號安全的函數(shù),也還是需要保存和恢復(fù)errno的。

異步信號不安全函數(shù)的原因有:

  • 使用靜態(tài)數(shù)據(jù)結(jié)構(gòu)

  • 使用glibc malloc/free函數(shù)

  • 使用標準io函數(shù)(比如printf)

信號處理中是不能使用這些不安全的函數(shù)的,否則后果很嚴重。觸類旁通,想想fork()之后、exec()之前,子進程在這段時間里,就只能調(diào)用異步信號安全函數(shù),這是一個道理的。

5 針對同一信號處理時再次發(fā)生的計數(shù)

傳統(tǒng)信號(編號從1到31)是不計次數(shù)的,只計是否發(fā)生過。實時信號(編號從32到64)是記錄次數(shù)的,當然是有上限的(通過ulimit查看)。

需要注意,計數(shù)區(qū)別不能成為評判信號可不可靠的標準,想想硬件中斷的處理就明白了。

6 總結(jié)

可靠信號要解決的問題,無非是(早期信號的)異步處理伴隨的競態(tài)窗口問題,可以說是通過sigprocmask和sigaction聯(lián)合解決了。最后要說的是,信號本質(zhì)就是軟件中斷,因為確實形神兼?zhèn)溆布袛?。?!?/span>

新浪微博(@NP等不等于P

計算機學習微信公眾號(jsj_xx)

原創(chuàng)技術(shù)文章,感悟計算機,透徹理解計算機!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多