Unix高級(jí)環(huán)境編程:信號(hào)

信號(hào),逗你玩

什么是中斷?

在計(jì)算機(jī)科學(xué)中,中斷是指由于接收到外圍硬件(相對(duì)于CPU與內(nèi)存而言)的異步信號(hào)或者來(lái)自軟件的同步信號(hào)而進(jìn)行相應(yīng)的硬件/軟件處理。

硬中斷?

顯然,外圍硬件發(fā)給CPU或者內(nèi)存的異步信號(hào)就是硬中斷信號(hào)。簡(jiǎn)言之:外設(shè)對(duì)CPU的中斷

軟中斷?

由軟件本身發(fā)給內(nèi)核的中斷信號(hào),稱之為軟中斷。通常是由硬中斷處理程序或進(jìn)程調(diào)度程序?qū)Σ僮飨到y(tǒng)內(nèi)核的中斷,也就是我們常說(shuō)的系統(tǒng)調(diào)用(System Call)了。

硬中斷與軟中斷之區(qū)別與聯(lián)系

  1. 硬中斷是有外設(shè)硬件發(fā)出的,需要有中斷控制器之參與。其過(guò)程是外設(shè)偵測(cè)到變化,告知中斷控制器,中斷控制器通過(guò)CPU或內(nèi)存的中斷腳通知CPU,然后硬件進(jìn)行程序計(jì)數(shù)器及堆棧寄存器之現(xiàn)場(chǎng)保存工作(引發(fā)上下文切換),并根據(jù)中斷向量調(diào)用硬中斷處理程序進(jìn)行中斷處理。
  2. 軟中斷則通常是由硬中斷處理程序或者進(jìn)程調(diào)度程序等軟件程序發(fā)出的中斷信號(hào),無(wú)需中斷控制器之參與,直接以一個(gè)CPU指令之形式指示CPU進(jìn)行程序計(jì)數(shù)器及堆棧寄存器之現(xiàn)場(chǎng)保存工作(亦會(huì)引發(fā)上下文切換),并調(diào)用相應(yīng)的軟中斷處理程序進(jìn)行中斷處理(即我們通常所言之系統(tǒng)調(diào)用)。
  3. 硬中斷直接以硬件的方式引發(fā),處理速度快。軟中斷以軟件指令之方式適合于對(duì)響應(yīng)速度要求不是特別嚴(yán)格的場(chǎng)景。
  4. 硬中斷通過(guò)設(shè)置CPU的屏蔽位可進(jìn)行屏蔽,軟中斷則由于是指令之方式給出,不能屏蔽。
  5. 硬中斷發(fā)生后,通常會(huì)在硬中斷處理程序中調(diào)用一個(gè)軟中斷來(lái)進(jìn)行后續(xù)工作的處理。
  6. 硬中斷和軟中斷均會(huì)引起上下文切換(進(jìn)程/線程之切換),進(jìn)程切換的過(guò)程是差不多的。

信號(hào)

信號(hào)是實(shí)現(xiàn)軟中斷的,不同的操作系統(tǒng)實(shí)現(xiàn)的信號(hào)不同。在mac中,信號(hào)的定義在如下文件中:


sys/signal.h
Screen Shot 2017-07-08 at 14.37.31.png
Screen Shot 2017-07-08 at 14.37.48.png
Screen Shot 2017-07-08 at 14.39.28.png
Screen Shot 2017-07-08 at 15.28.25.png
Screen Shot 2017-07-08 at 15.27.02.png

每次CTL+C 產(chǎn)生中斷信號(hào),CTL+Z可以中斷任務(wù),跳出該死循環(huán)

終止+core文件

在一個(gè)進(jìn)程異常終止時(shí),在一定的條件下,會(huì)在當(dāng)前工作目錄下生成一個(gè)core文件。
core文件是該進(jìn)程(異常終止時(shí))的內(nèi)存映像(同時(shí)加上調(diào)試信息)。大多數(shù)調(diào)試程序都使用 core 文件以檢查進(jìn)程終止時(shí)的狀態(tài)。

core文件

信號(hào)處理流程

流程

unix 信號(hào)處理方式

1、忽略信號(hào):sigkill和sigstop不可行
2、捕獲信號(hào):用戶捕獲信號(hào),執(zhí)行自己的操作
3、執(zhí)行系統(tǒng)默認(rèn)操作:信號(hào)發(fā)生時(shí)系統(tǒng)默認(rèn)的操作

可靠信號(hào)和不可靠信號(hào)

在早期的UNIX中信號(hào)是不可靠的,不可靠在這里指的是:信號(hào)可能丟失,一個(gè)信號(hào)發(fā)生了,但進(jìn)程卻可能一直不知道這一點(diǎn)。
現(xiàn)在 在SIGRTMIN實(shí)時(shí)信號(hào)之前的都叫不可靠信號(hào),這里的不可靠主要是不支持信號(hào)隊(duì)列,就是當(dāng)多個(gè)信號(hào)發(fā)生在進(jìn)程中的時(shí)候(收到信號(hào)的速度超過(guò)進(jìn)程處理的速度的時(shí)候),這些沒(méi)來(lái)的及處理的信號(hào)就會(huì)被丟掉,僅僅留下一個(gè)信號(hào)。
可靠信號(hào)是多個(gè)信號(hào)發(fā)送到進(jìn)程的時(shí)候(收到信號(hào)的速度超過(guò)進(jìn)程處理信號(hào)的速度的時(shí)候),這些沒(méi)來(lái)的及處理的信號(hào)就會(huì)排入進(jìn)程的隊(duì)列。等進(jìn)程有機(jī)會(huì)來(lái)處理的時(shí)候,依次再處理,信號(hào)不丟失。

信號(hào)在內(nèi)核中的表示:

信號(hào)遞達(dá)delivery:實(shí)際執(zhí)行信號(hào)處理信號(hào)的動(dòng)作
信號(hào)未決pending:信號(hào)從產(chǎn)生到抵達(dá)之間的狀態(tài),信號(hào)產(chǎn)生了但是未處理
忽略:抵達(dá)之后的一種 動(dòng)作
阻塞block:收到信號(hào)不立即處理被阻塞的信號(hào)將保持未決狀態(tài),直到進(jìn)程解除對(duì)此信號(hào)的阻塞,才執(zhí)行抵達(dá)動(dòng)作

信號(hào)產(chǎn)生和阻塞沒(méi)有直接關(guān)系 抵達(dá)和解除阻塞沒(méi)有直接關(guān)系!
進(jìn)程收到一個(gè)信號(hào)后,不會(huì)立即處理,它會(huì)在恰當(dāng)?shù)臅r(shí)機(jī)被處理。

中斷的系統(tǒng)調(diào)用

如果進(jìn)程在執(zhí)行一個(gè)低速系統(tǒng)調(diào)用而阻塞期間捕捉到一個(gè)信號(hào),該系統(tǒng)調(diào)用就被終端不再繼續(xù)執(zhí)行。該系統(tǒng)調(diào)用返回出錯(cuò),其errno被設(shè)置為EINTR。現(xiàn)在操作系統(tǒng)引入了某些中斷系統(tǒng)調(diào)用的自動(dòng)重啟動(dòng):自動(dòng)重啟動(dòng)的系統(tǒng)調(diào)用包括:ioctl,read,readv,write,writev,wait和waitpid。其中前5個(gè)函數(shù)只有對(duì)低速設(shè)備進(jìn)行操作時(shí)才會(huì)被信號(hào)終端。而wait和waitpid在捕捉到信號(hào)時(shí)總是被終端。

捕獲.PNG
捕獲1.PNG

可重入函數(shù)

用于多任務(wù)環(huán)境中,一個(gè)可重入的函數(shù)簡(jiǎn)單來(lái)說(shuō)就是可以被中斷的函數(shù),也就是說(shuō),可以在這個(gè)函數(shù)執(zhí)行的任何時(shí)刻中斷它,轉(zhuǎn)入OS調(diào)度下去執(zhí)行另外一段代碼,而返![Uploading 捕獲_303775.PNG . . .]
回控制時(shí)不會(huì)出現(xiàn)什么錯(cuò)誤;而不可重入的函數(shù)由于使用了一些系統(tǒng)資源,比如全局變量區(qū),中斷向量表等,所以它如果被中斷的話,可能會(huì)出現(xiàn)問(wèn)題,這類函數(shù)是不能運(yùn)行在多任務(wù)環(huán)境下的。
編寫(xiě)可重入函數(shù)時(shí),若使用全局變量,則應(yīng)通過(guò)關(guān)中斷、信號(hào)量(即P、V操作)等手段對(duì)其加以保護(hù)。

signaction

int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
stuct sigaction  
{  
  void (*)(int) sa_handle;  
  sigset_t sa_mask;  
  int sa_flags;  
}  
  1. 阻塞,sigaction函數(shù)有阻塞的功能,比如SIGINT信號(hào)來(lái)了,進(jìn)入信號(hào)處理函數(shù),默認(rèn)情況下,在信號(hào)處理函數(shù)未完成之前,如果又來(lái)了一個(gè)SIGINT信號(hào),其將被阻塞,只有信號(hào)處理函數(shù)處理完畢,才會(huì)對(duì)后來(lái)的SIGINT再進(jìn)行處理,同時(shí)后續(xù)無(wú)論來(lái)多少個(gè)SIGINT,僅處理一個(gè)SIGINT,sigaction會(huì)對(duì)后續(xù)SIGINT進(jìn)行排隊(duì)合并處理。
  2. sa_mask,信號(hào)屏蔽集,可以通過(guò)函數(shù)sigemptyset/sigaddset等來(lái)清空和增加需要屏蔽的信號(hào),上面代碼中,對(duì)信號(hào)SIGINT處理時(shí),如果來(lái)信號(hào)SIGQUIT,其將被屏蔽,但是如果在處理SIGQUIT,來(lái)了SIGINT,則首先處理SIGINT,然后接著處理SIGQUIT。
  3. sa_flags如果取值為0,則表示默認(rèn)行為。還可以取如下倆值,但是我沒(méi)覺(jué)得這倆值有啥用。
    SA_NODEFER,如果設(shè)置來(lái)該標(biāo)志,則不進(jìn)行當(dāng)前處理信號(hào)到阻塞
    SA_RESETHAND,如果設(shè)置來(lái)該標(biāo)志,則處理完當(dāng)前信號(hào)后,將信號(hào)處理函數(shù)設(shè)置為SIG_DFL行為
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容