linux+向进城发送信号,信号 - it610.com
Linux中有兩種類(lèi)型信號(hào)
常規(guī)信號(hào)(regular signal):編碼范圍為1~31,同種類(lèi)型的常規(guī)信號(hào)如果被發(fā)送多次,那么,只有其中的一個(gè)發(fā)送到接收進(jìn)城
實(shí)時(shí)信號(hào)(real-time signal):編碼范圍32~64,它與常規(guī)信號(hào)不通,因?yàn)樗麄儽仨毰抨?duì)以便發(fā)送的多個(gè)信號(hào)能被接收到。盡管linux內(nèi)核不使用實(shí)時(shí)信號(hào),它還是通過(guò)幾個(gè)特定的系統(tǒng)調(diào)用完全實(shí)現(xiàn)了POSIX標(biāo)準(zhǔn)。
與信號(hào)相關(guān)的最重要的系統(tǒng)調(diào)用
kill() ? ? ? ? 向線程組發(fā)送一個(gè)信號(hào)
tkill() ? ? ? ?向進(jìn)程發(fā)送一個(gè)信號(hào)
tgkill() ? ? ? 向一個(gè)特定線程組中的進(jìn)程發(fā)送信號(hào)
sigaction() ? ?改變與信號(hào)相關(guān)的操作
signal() ? ? ? 類(lèi)似于sigaction()
sigpending() ? 檢查是否有掛起信號(hào)
sigprocmask() ?修改阻塞信號(hào)的集合
sigsuspend() ? 等待一個(gè)信號(hào)
信號(hào)的一個(gè)重要特點(diǎn)是它們可以隨時(shí)隨地發(fā)送給狀態(tài)經(jīng)常不可預(yù)知的進(jìn)程。發(fā)送給非運(yùn)行進(jìn)程的信號(hào)必須由內(nèi)核保存,直到進(jìn)程恢復(fù)執(zhí)行。
內(nèi)核區(qū)分信號(hào)傳遞的兩個(gè)不同階段:
信號(hào)產(chǎn)生
內(nèi)核更新目標(biāo)進(jìn)程的數(shù)據(jù)結(jié)構(gòu)以表示一個(gè)新信號(hào)已被發(fā)送。
信號(hào)傳遞
內(nèi)核強(qiáng)迫目標(biāo)進(jìn)程通過(guò)以下方式對(duì)信號(hào)做出反應(yīng):或改變目標(biāo)進(jìn)程的執(zhí)行狀態(tài),或開(kāi)始執(zhí)行一個(gè)特定的信號(hào)處理程序,或者兩者都是。
已經(jīng)產(chǎn)生但還沒(méi)有傳遞的信號(hào)稱為掛起信號(hào)(pending signal)。任何時(shí)候,一個(gè)進(jìn)程僅存在給定類(lèi)型的一個(gè)掛起信號(hào),同一進(jìn)程同種類(lèi)型的其他信號(hào)不被排隊(duì),只被簡(jiǎn)單的丟棄。但是,實(shí)時(shí)信號(hào)時(shí)不同的:同種類(lèi)型的掛起信號(hào)可以多個(gè)。
盡管信號(hào)表項(xiàng)比較直觀,但內(nèi)核實(shí)現(xiàn)相當(dāng)復(fù)雜:
1、記住每個(gè)進(jìn)程阻塞哪些信號(hào)
2、當(dāng)從內(nèi)核態(tài)切換到用戶態(tài)時(shí),對(duì)任何一個(gè)進(jìn)程都要檢查是否有一個(gè)信號(hào)到達(dá)。這幾乎在每個(gè)定時(shí)器中斷都發(fā)送
3、確定是否可以忽略信號(hào)。這發(fā)生在下列所有條件都滿足時(shí):
a、目標(biāo)進(jìn)程沒(méi)有被另一個(gè)進(jìn)程跟蹤
b、信號(hào)沒(méi)有被目標(biāo)進(jìn)程阻塞
c、信號(hào)被目標(biāo)進(jìn)程屏蔽
4、處理這樣的信號(hào),即信號(hào)可能在進(jìn)程運(yùn)行期間的任一時(shí)刻請(qǐng)求把進(jìn)程切換到一個(gè)信號(hào)處理函數(shù),并在這個(gè)函數(shù)返回后恢復(fù)原來(lái)執(zhí)行的上下文。
進(jìn)程以三種方式對(duì)一個(gè)信號(hào)做出應(yīng)答:
1、顯示地忽略信號(hào)
2、執(zhí)行與信號(hào)相關(guān)的缺省操作
3、通過(guò)調(diào)用相應(yīng)的信號(hào)處理函數(shù)捕獲信號(hào)
注意,對(duì)一個(gè)信號(hào)的阻塞和忽略是不同的:只要信號(hào)被阻塞,它就不被傳遞;只有信號(hào)解除阻塞后才傳遞它。而一個(gè)被忽略的信號(hào)總是被傳遞,只是沒(méi)有進(jìn)一步的操作。
SIGKILL和SIGSTOP信號(hào)不可以被顯式地忽略、捕獲或阻塞,因此,通常必須執(zhí)行它們的缺省操作。
POSIX標(biāo)準(zhǔn)對(duì)多線程應(yīng)用的信號(hào)處理有一些嚴(yán)格的要求:
1、信號(hào)處理程序必須在多線程應(yīng)用的所有線程之間共享;不過(guò),每個(gè)線程必須有自己的掛起信號(hào)掩碼和阻塞信號(hào)掩碼
2、每個(gè)發(fā)送給多線程應(yīng)用的信號(hào)僅傳送給一個(gè)線程,這個(gè)線程是由內(nèi)核在從不阻塞該信號(hào)的線程中隨意選擇出來(lái)的
3、如果向多線程應(yīng)用發(fā)送了一個(gè)致命的信號(hào),那么內(nèi)核將殺死該應(yīng)用的所有線程,而不僅僅是殺死接收信號(hào)的那個(gè)線程。
task_struct線程描述符中與信號(hào)相關(guān)的字段
struct signal_struct *signal;
struct sighand_struct *sighand;
struct sigpending pending;
產(chǎn)生信號(hào)
很多內(nèi)核函數(shù)都會(huì)產(chǎn)生信號(hào):它們完成信號(hào)處理第一步的工作,即根據(jù)需要更新一個(gè)或多個(gè)進(jìn)程的描述符。它們不直接執(zhí)行第二步的信號(hào)傳遞操作,而是可能可能根據(jù)信號(hào)的類(lèi)型和目標(biāo)進(jìn)程的狀態(tài)喚醒一下進(jìn)程,并促使這些進(jìn)程接收信號(hào)。
當(dāng)發(fā)送給進(jìn)程一個(gè)信號(hào)時(shí),這個(gè)信號(hào)可能來(lái)自內(nèi)核,也可能來(lái)自另一個(gè)進(jìn)程
傳遞信號(hào)
假定內(nèi)核已經(jīng)注意到一個(gè)信號(hào)的到來(lái),并調(diào)用前面介紹的函數(shù)為接收此信號(hào)的進(jìn)程準(zhǔn)備描述符。但萬(wàn)一這個(gè)進(jìn)程在那一刻并不在CPU運(yùn)行,內(nèi)核就延遲傳遞函數(shù)的任務(wù)。那么如何確保進(jìn)程的掛起信號(hào)得到處理呢?
內(nèi)核在運(yùn)行進(jìn)程恢復(fù)用戶態(tài)下的執(zhí)行前,檢查進(jìn)程TIF_SIGPENDING標(biāo)志的值。每當(dāng)內(nèi)核處理完一個(gè)中斷或異常時(shí),就檢查是否存在掛起的信號(hào)。
捕獲信號(hào)
上圖說(shuō)明了有關(guān)捕獲一個(gè)信號(hào)的函數(shù)的執(zhí)行流。一個(gè)非阻塞的信號(hào)發(fā)送給一個(gè)進(jìn)程。當(dāng)中斷或異常發(fā)生時(shí),進(jìn)程切換到內(nèi)核態(tài)。正要返回到用戶態(tài)前,內(nèi)核執(zhí)行do_signal()函數(shù),這個(gè)函數(shù)又依次處理信號(hào)和建立用戶態(tài)堆棧。當(dāng)進(jìn)程又切換到用戶態(tài)時(shí)因?yàn)樾盘?hào)處理程序的起始地址被強(qiáng)制放進(jìn)程序計(jì)數(shù)器中,因此開(kāi)始執(zhí)行信號(hào)處理程序。當(dāng)處理程序終止時(shí),setup_frame()函數(shù)放在用戶態(tài)堆棧中的返回代碼被執(zhí)行。這個(gè)代碼調(diào)用sigreturn()系統(tǒng)調(diào)用,相應(yīng)的服務(wù)例程把正常程序的用戶態(tài)堆棧硬件上下文拷貝到內(nèi)核態(tài)堆棧,并把用戶態(tài)堆?;謴?fù)到原來(lái)的狀態(tài)。當(dāng)這個(gè)系統(tǒng)調(diào)用結(jié)束時(shí),普通進(jìn)程就因此能恢復(fù)自己的執(zhí)行。
總結(jié)
以上是生活随笔為你收集整理的linux+向进城发送信号,信号 - it610.com的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux插光驱自动重启,Linux两种
- 下一篇: linux32安装pgsql,Linux