當(dāng)我們?cè)趙in上遇到一個(gè)沒有辦法正常關(guān)閉的軟件的時(shí)候,我們可以打開任務(wù)管理器,強(qiáng)制結(jié)束這個(gè)進(jìn)程,同理。在linux上也有類似的功能,比如從終端敲入ctrl+c組合鍵來產(chǎn)生一個(gè)信號(hào),當(dāng)運(yùn)行中的進(jìn)程捕捉到這個(gè)信號(hào)后就會(huì)做出反應(yīng)。 我們?cè)趙in上可以使用快捷鍵進(jìn)入任務(wù)管理器,那么linux中會(huì)在哪些情況下會(huì)產(chǎn)生信號(hào)呢?
1042070qdq6x0khacs0x45.jpg (5.45 KB, 下載次數(shù): 50)
下載附件
2019-9-11 02:19 上傳
那么linux有多少種信號(hào)呢,我們可以通過命令kill命令來查看,如下圖:
104207yh5ahnlxshnprl1p.jpg (20.29 KB, 下載次數(shù): 46)
下載附件
2019-9-11 02:19 上傳
通過上面的截圖我們可以發(fā)現(xiàn),一共有64種信號(hào),每個(gè)信號(hào)都是以sig開頭,信號(hào)的名稱是在signal.h中定義的。 本次文章主要涉及到三個(gè)內(nèi)容,一,信號(hào)的發(fā)送,二,信號(hào)的接收,三,信號(hào)的處理。 第一部分:信號(hào)的發(fā)送 我們通過一個(gè)小例子來認(rèn)識(shí)下信號(hào)的發(fā)送:
104207al95ztdzaeyd3nzx.jpg (10.81 KB, 下載次數(shù): 50)
下載附件
2019-9-11 02:19 上傳
這個(gè)程序主要用到了kill函數(shù), 因?yàn)橛脩艨臻g是不具備發(fā)送信號(hào)的能力的,只有內(nèi)核才可以發(fā)信號(hào),內(nèi)核有那么多信號(hào),我們要發(fā)哪個(gè)信號(hào),并且發(fā)給誰呢?那么我們就需要先告訴內(nèi)核進(jìn)程PID,信號(hào)ID是多少,kill函數(shù)就幫我們解決了這個(gè)問題,函數(shù)原型:
104207h7ofzhf4555rk7kd.jpg (22.06 KB, 下載次數(shù): 49)
下載附件
2019-9-11 02:19 上傳
所以在上面的例子中,我們就可以通過kill函數(shù)來向內(nèi)核發(fā)送一次產(chǎn)生信號(hào)的請(qǐng)求。 我們?cè)賮砜匆粋(gè)和kill函數(shù)很像的函數(shù),raise函數(shù) ,與kill函數(shù)不同的是,它沒有第一個(gè)參數(shù),他不知道要發(fā)信號(hào)給誰,所以他只能發(fā)信號(hào)給自己。我們來看下這個(gè)例子:
10420706r46odgr6rp69a6.jpg (10.55 KB, 下載次數(shù): 60)
下載附件
2019-9-11 02:19 上傳
編譯并運(yùn)行:
1042070ht26ftb4o5ouobi.jpg (6.56 KB, 下載次數(shù): 46)
下載附件
2019-9-11 02:19 上傳
函數(shù)原型:
1042073tab0c2ozweitoia.jpg (9.53 KB, 下載次數(shù): 48)
下載附件
2019-9-11 02:19 上傳
從kill和raise的函數(shù)原型上看,raise沒有pid這個(gè)參數(shù),所以raise是可以通過kill來實(shí)現(xiàn)的。等價(jià)于:
1042075mlivm8zurp7mrrv.jpg (3.63 KB, 下載次數(shù): 43)
下載附件
2019-9-11 02:19 上傳
還有一個(gè)需要了解的函數(shù)alarm函數(shù),與raise函數(shù)不同的是,他只能發(fā)alarm信號(hào),并且可以定時(shí)發(fā)送信號(hào),而raise是立刻讓內(nèi)核發(fā)信號(hào)。所以這個(gè)函數(shù)的參數(shù)沒有pid號(hào),也沒有信號(hào)ID,只有一個(gè)延遲的秒數(shù)。需要注意的是,一個(gè)進(jìn)程只能有一個(gè)alarm時(shí)間,函數(shù)原型:
1042082900lz9pzqthzb0p.jpg (6.94 KB, 下載次數(shù): 43)
下載附件
2019-9-11 02:19 上傳
第一部分信號(hào)發(fā)送總結(jié): 用戶空間不能發(fā)送信號(hào),是通過系統(tǒng)調(diào)用函數(shù)告訴內(nèi)核發(fā)什么信號(hào),發(fā)給誰,讓內(nèi)核來發(fā)送的,只有內(nèi)核才可以發(fā)信號(hào)?梢允褂胟ill,raise,alarm函數(shù)來讓內(nèi)核發(fā)送信號(hào)。 第二部分信號(hào)接收 我們可以使用pause來接收信號(hào),pause函數(shù)使該進(jìn)程暫停讓出CPU。我們來看下下面這個(gè)例子,當(dāng)我們?cè)阪I盤上按下ctrl+c的時(shí)候,程序收到SIGINT信號(hào)會(huì)被喚醒,然后執(zhí)行fun函數(shù),處理完之后再返回繼續(xù)運(yùn)行該程序,不按則只打印process start(進(jìn)入睡眠狀態(tài))。
104208im43k9mxi3zbq4dx.jpg (6.38 KB, 下載次數(shù): 53)
下載附件
2019-9-11 02:19 上傳
函數(shù)原型:
104208nrp9pyzrbpx6rxup.jpg (5.45 KB, 下載次數(shù): 38)
下載附件
2019-9-11 02:19 上傳
第三部分信號(hào)處理 信號(hào)的處理有三種方式,分別為:1,忽略,就是收到信號(hào)后,什么也不做,不處理。2,按照默認(rèn)的方式處理。3,捕獲并處理,捕獲到信號(hào)后,執(zhí)行我們自己想執(zhí)行的代碼。我們先來看下signal函數(shù):
104208iayngctc4dyaquib.jpg (8.67 KB, 下載次數(shù): 42)
下載附件
2019-9-11 02:19 上傳
第一種處理方式,忽略: 我們來看下這個(gè)例子。
104208anzx0jdj6dd1a2y2.jpg (6.68 KB, 下載次數(shù): 42)
下載附件
2019-9-11 02:19 上傳
編譯并運(yùn)行,因?yàn)槲覀兪褂玫膮?shù)為SIG_IGN,所以我們按下ctrl+c的時(shí)候并不能中斷程序運(yùn)行.
104208qtxtid8hto4cx0cn.jpg (9.04 KB, 下載次數(shù): 47)
下載附件
2019-9-11 02:19 上傳
第二種處理方式,按照默認(rèn)的方式處理,我們把上個(gè)例子中的參數(shù)改成SIG_DFL,如下:
1042081smvik45c1ci7ksv.jpg (7.15 KB, 下載次數(shù): 48)
下載附件
2019-9-11 02:19 上傳
編譯并運(yùn)行,當(dāng)我們按下ctrl+c的時(shí)候,會(huì)中斷我們程序。
104208j8jptpl8hg9xl7l7.jpg (8.53 KB, 下載次數(shù): 46)
下載附件
2019-9-11 02:19 上傳
第三種處理方式,執(zhí)行我們自己的代碼:
104208xpa8hq6appiiq7bw.jpg (7.8 KB, 下載次數(shù): 48)
下載附件
2019-9-11 02:19 上傳
當(dāng)我們按下ctrl+c的時(shí)候,會(huì)進(jìn)去到fun函數(shù)。
104208gw55uuswulo0utgu.jpg (7.73 KB, 下載次數(shù): 49)
下載附件
2019-9-11 02:19 上傳
三個(gè)部分總結(jié): 1,我們可以使用kill命令來查看有多少個(gè)信號(hào),在這么多信號(hào)中,我們要格外記住以下幾個(gè):
104208zgys9wgbgts9sjbn.jpg (10.86 KB, 下載次數(shù): 40)
下載附件
2019-9-11 02:19 上傳
2,用戶空間不能發(fā)送信號(hào),信號(hào)的產(chǎn)生來自內(nèi)核,讓內(nèi)核產(chǎn)生信號(hào)的方式有:通過鍵盤輸入ctrl+c等。當(dāng)程序運(yùn)行出錯(cuò)時(shí),內(nèi)核會(huì)給進(jìn)程發(fā)送一個(gè)信號(hào),如浮點(diǎn)溢出等,還有就是一個(gè)程序可以通過調(diào)用函數(shù)來給另外一個(gè)進(jìn)程發(fā)信號(hào),如kill。 3,進(jìn)程收到信號(hào)后,可以忽略,或者按照默認(rèn)的方式處理,或者按照自己的處理函數(shù)來處理,signale是永久注冊(cè)的,每次都有效,如果不想的話這樣可以使用sigaction。 |