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