進(jìn)程間通信之:信號(hào)
8.3信號(hào)
8.3.1信號(hào)概述
信號(hào)是UNIX中所使用的進(jìn)程通信的一種最古老的方法。它是在軟件層次上對(duì)中斷機(jī)制的一種模擬,是一種異步通信方式。信號(hào)可以直接進(jìn)行用戶空間進(jìn)程和內(nèi)核進(jìn)程之間的交互,內(nèi)核進(jìn)程也可以利用它來通知用戶空間進(jìn)程發(fā)生了哪些系統(tǒng)事件。它可以在任何時(shí)候發(fā)給某一進(jìn)程,而無需知道該進(jìn)程的狀態(tài)。如果該進(jìn)程當(dāng)前并未處于執(zhí)行態(tài),則該信號(hào)就由內(nèi)核保存起來,直到該進(jìn)程恢復(fù)執(zhí)行再傳遞給它為止;如果一個(gè)信號(hào)被進(jìn)程設(shè)置為阻塞,則該信號(hào)的傳遞被延遲,直到其阻塞被取消時(shí)才被傳遞給進(jìn)程。
在第2章kill命令中曾講解到“−l”選項(xiàng),這個(gè)選項(xiàng)可以列出該系統(tǒng)所支持的所有信號(hào)的列表。在筆者的系統(tǒng)中,信號(hào)值在32之前的則有不同的名稱,而信號(hào)值在32以后的都是用“SIGRTMIN”或“SIGRTMAX”開頭的,這就是兩類典型的信號(hào)。前者是從UNIX系統(tǒng)中繼承下來的信號(hào),為不可靠信號(hào)(也稱為非實(shí)時(shí)信號(hào));后者是為了解決前面“不可靠信號(hào)”的問題而進(jìn)行了更改和擴(kuò)充的信號(hào),稱為“可靠信號(hào)”(也稱為實(shí)時(shí)信號(hào))。那么為什么之前的信號(hào)不可靠呢?這里首先要介紹一下信號(hào)的生命周期。
一個(gè)完整的信號(hào)生命周期可以分為3個(gè)重要階段,這3個(gè)階段由4個(gè)重要事件來刻畫的:信號(hào)產(chǎn)生、信號(hào)在進(jìn)程中注冊(cè)、信號(hào)在進(jìn)程中注銷、執(zhí)行信號(hào)處理函數(shù),如圖8.6所示。相鄰兩個(gè)事件的時(shí)間間隔構(gòu)成信號(hào)生命周期的一個(gè)階段。要注意這里的信號(hào)處理有多種方式,一般是由內(nèi)核完成的,當(dāng)然也可以由用戶進(jìn)程來完成,故在此沒有明確畫出。
圖8.6信號(hào)生命周期
一個(gè)不可靠信號(hào)的處理過程是這樣的:如果發(fā)現(xiàn)該信號(hào)已經(jīng)在進(jìn)程中注冊(cè),那么就忽略該信號(hào)。因此,若前一個(gè)信號(hào)還未注銷又產(chǎn)生了相同的信號(hào)就會(huì)產(chǎn)生信號(hào)丟失。而當(dāng)可靠信號(hào)發(fā)送給一個(gè)進(jìn)程時(shí),不管該信號(hào)是否已經(jīng)在進(jìn)程中注冊(cè),都會(huì)被再注冊(cè)一次,因此信號(hào)就不會(huì)丟失。所有可靠信號(hào)都支持排隊(duì),而所有不可靠信號(hào)都不支持排隊(duì)。
注意 | 這里信號(hào)的產(chǎn)生、注冊(cè)和注銷等是指信號(hào)的內(nèi)部實(shí)現(xiàn)機(jī)制,而不是調(diào)用信號(hào)的函數(shù)實(shí)現(xiàn)。因此,信號(hào)注冊(cè)與否,與本節(jié)后面講到的發(fā)送信號(hào)函數(shù)(如kill()等)以及信號(hào)安裝函數(shù)(如signal()等)無關(guān),只與信號(hào)值有關(guān)。 |
用戶進(jìn)程對(duì)信號(hào)的響應(yīng)可以有3種方式。
n 忽略信號(hào),即對(duì)信號(hào)不做任何處理,但是有兩個(gè)信號(hào)不能忽略,即SIGKILL及SIGSTOP。
n 捕捉信號(hào),定義信號(hào)處理函數(shù),當(dāng)信號(hào)發(fā)生時(shí),執(zhí)行相應(yīng)的自定義處理函數(shù)。
n 執(zhí)行缺省操作,Linux對(duì)每種信號(hào)都規(guī)定了默認(rèn)操作。
Linux中的大多數(shù)信號(hào)是提供給內(nèi)核的,表8.6列出了Linux中最為常見信號(hào)的含義及其默認(rèn)操作。
表8.6 常見信號(hào)的含義及其默認(rèn)操作
信號(hào)名 | 含義 | 默認(rèn)操作 |
SIGHUP | 該信號(hào)在用戶終端連接(正?;蚍钦#┙Y(jié)束時(shí)發(fā)出,通常是在終端的控制進(jìn)程結(jié)束時(shí),通知同一會(huì)話內(nèi)的各個(gè)作業(yè)與控制終端不再關(guān)聯(lián) | 終止 |
SIGINT | 該信號(hào)在用戶鍵入INTR字符(通常是Ctrl-C)時(shí)發(fā)出,終端驅(qū)動(dòng)程序發(fā)送此信號(hào)并送到前臺(tái)進(jìn)程中的每一個(gè)進(jìn)程 | 終止 |
SIGQUIT | 該信號(hào)和SIGINT類似,但由QUIT字符(通常是Ctrl-)來控制 | 終止 |
SIGILL | 該信號(hào)在一個(gè)進(jìn)程企圖執(zhí)行一條非法指令時(shí)(可執(zhí)行文件本身出現(xiàn)錯(cuò)誤,或者試圖執(zhí)行數(shù)據(jù)段、堆棧溢出時(shí))發(fā)出 | 終止 |
SIGFPE | 該信號(hào)在發(fā)生致命的算術(shù)運(yùn)算錯(cuò)誤時(shí)發(fā)出。這里不僅包括浮點(diǎn)運(yùn)算錯(cuò)誤,還包括溢出及除數(shù)為0等其他所有的算術(shù)錯(cuò)誤 | 終止 |
SIGKILL | 該信號(hào)用來立即結(jié)束程序的運(yùn)行,并且不能被阻塞、處理或忽略 | 終止 |
SIGALRM | 該信號(hào)當(dāng)一個(gè)定時(shí)器到時(shí)的時(shí)候發(fā)出 | 終止 |
SIGSTOP | 該信號(hào)用于暫停一個(gè)進(jìn)程,且不能被阻塞、處理或忽略 | 暫停進(jìn)程 |
SIGTSTP | 該信號(hào)用于交互停止進(jìn)程,用戶鍵入SUSP字符時(shí)(通常是Ctrl+Z)發(fā)出這個(gè)信號(hào) | 停止進(jìn)程 |
SIGCHLD | 子進(jìn)程改變狀態(tài)時(shí),父進(jìn)程會(huì)收到這個(gè)信號(hào) | 忽略 |
SIGABORT | 進(jìn)程異常終止時(shí)發(fā)出 |
模擬信號(hào)相關(guān)文章:什么是模擬信號(hào)
linux相關(guān)文章:linux教程
數(shù)字通信相關(guān)文章:數(shù)字通信原理
通信相關(guān)文章:通信原理
評(píng)論