當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 學(xué)習(xí)筆記 > linux進(jìn)程間通信信號(hào)
信 號(hào) :
同步通信:按照某種順序依次做事情。
異步通信:接收到某個(gè)信號(hào),去執(zhí)行某個(gè)操作,然后再接著做之前的事情阻塞:沒(méi)有等到結(jié)果,不做其他事情,一直等待
非阻塞:沒(méi)有等到結(jié)果,直接返回。信號(hào)是唯一一種異步通信的方式
信號(hào)是信息的載體,Linux/UNIX 環(huán)境下,古老、經(jīng)典的通信方式, 現(xiàn)下依然是主要的通信手段。Unix早期版本就提供了信號(hào)機(jī)制,但不可靠,信號(hào)可能丟失。Berkeley 和
AT&T都對(duì)信號(hào)模型做了更改,增加了可靠信號(hào)機(jī)制。但彼此不兼容。POSIX.1對(duì)可靠信號(hào)例程進(jìn)行了標(biāo)準(zhǔn)化。
一個(gè)完整的信號(hào)生命周期可以分為3個(gè)重要階段,這3個(gè)階段由4個(gè)重要事件來(lái)刻畫(huà)
$信號(hào)產(chǎn)生
$信號(hào)在進(jìn)程中注冊(cè)
$信號(hào)在進(jìn)程中注銷(xiāo)
$執(zhí)行信號(hào)處理函數(shù)
相鄰兩個(gè)事件的時(shí)間間隔構(gòu)成信號(hào)生命周期的一個(gè)階段
信號(hào)處理有多種方式,一般是由內(nèi)核完成的,當(dāng)然也可以有用戶進(jìn)程完成不可靠信號(hào)的處理過(guò)程(信號(hào)值在32號(hào)之前)
$發(fā)現(xiàn)該信號(hào)已經(jīng)在進(jìn)程中注冊(cè),則忽略該信號(hào)
$故若前一個(gè)信號(hào)還未注銷(xiāo)又產(chǎn)生了相同的信號(hào)就會(huì)產(chǎn)生信號(hào)丟失可靠信號(hào)的處理過(guò)程(信號(hào)值在32號(hào)之后)
$發(fā)現(xiàn)信號(hào)不管該信號(hào)是否已經(jīng)在進(jìn)程中注冊(cè),都會(huì)被再注冊(cè)所有可靠信號(hào)都支持排隊(duì),而不可靠信號(hào)則都不支持排隊(duì)
信號(hào)的機(jī)制:
A給B發(fā)送信號(hào),B收到信號(hào)之前執(zhí)行自己的代碼,收到信號(hào)后,不管執(zhí)行到程序的什
么位置,都要暫停運(yùn)行,去處理信號(hào),處理完畢再繼續(xù)執(zhí)行。與硬件中斷類似——異步模 式。但信號(hào)是軟件層面上實(shí)現(xiàn)的中斷,早期常被稱為“軟中斷”。
信號(hào)的特質(zhì):由于信號(hào)是通過(guò)軟件方法實(shí)現(xiàn),其實(shí)現(xiàn)手段導(dǎo)致信號(hào)有很強(qiáng)的延時(shí)性。 但對(duì)于用戶來(lái)說(shuō),這個(gè)延遲時(shí)間非常短,不易察覺(jué)。
每個(gè)進(jìn)程收到的所有信號(hào),都是由內(nèi)核負(fù)責(zé)發(fā)送的,內(nèi)核處理。
與信號(hào)相關(guān)的事件和狀態(tài)
產(chǎn)生信號(hào):
1. 按鍵產(chǎn)生,如:Ctrl+c、Ctrl+z、Ctrl+\
2. 系統(tǒng)調(diào)用產(chǎn)生,如:kill、raise、abort
3. 軟件條件產(chǎn)生,如:定時(shí)器alarm
4. 硬件異常產(chǎn)生,如:非法訪問(wèn)內(nèi)存(段錯(cuò)誤)、除0(浮點(diǎn)數(shù)例外)、內(nèi)存對(duì)齊出錯(cuò)
(總線錯(cuò)誤)
5. 命令產(chǎn)生,如:kill命令遞達(dá):遞送并且到達(dá)進(jìn)程。
未決:產(chǎn)生和遞達(dá)之間的狀態(tài)。主要由于阻塞(屏蔽)導(dǎo)致該狀態(tài)。 信號(hào)的處理方式:
1. 執(zhí)行默認(rèn)動(dòng)作,由Linux規(guī)定的默認(rèn)操作。
2. 忽略(丟棄);SIGKILL及SIGSTOP不可被忽略。
3. 捕捉(調(diào)用戶處理函數(shù))
Linux內(nèi)核的進(jìn)程控制塊PCB是一個(gè)結(jié)構(gòu)體,task_struct, 除了包含進(jìn)程id,狀態(tài),工作目錄,用戶id,組id,文件描述符表,還包含了信號(hào)相關(guān)的信息,主要指阻塞信號(hào)集和未決信號(hào)集。
阻塞信號(hào)集(信號(hào)屏蔽字): 將某些信號(hào)加入集合,對(duì)他們?cè)O(shè)置屏蔽,當(dāng)屏蔽x信號(hào)后,再收到該信號(hào),該信號(hào)的處理將推后(解除屏蔽后)
未決信號(hào)集:
1. 信號(hào)產(chǎn)生,未決信號(hào)集中描述該信號(hào)的位立刻翻轉(zhuǎn)為1,表信號(hào)處于未決狀態(tài)。當(dāng)信號(hào)被處理對(duì)應(yīng)位翻轉(zhuǎn)回為0。這一時(shí)刻往往非常短暫。
2. 信號(hào)產(chǎn)生后由于某些原因(主要是阻塞)不能抵達(dá)。這類信號(hào)的集合稱之為未決信 號(hào)集。在屏蔽解除前,信號(hào)一直處于未決狀態(tài)。
查看所有的信號(hào): kill -l
信號(hào)四要素:
與變量三要素類似的,每個(gè)信號(hào)也有其必備4要素,分別是:
1. 編號(hào) 2. 名稱 3. 事件 4. 默認(rèn)處理動(dòng)作
不同的操作系統(tǒng)定義了不同的系統(tǒng)信號(hào)。因此有些信號(hào)出現(xiàn)在Unix系統(tǒng)內(nèi),也出現(xiàn)在
Linux中,而有的信號(hào)出現(xiàn)在FreeBSD或Mac OS中卻沒(méi)有出現(xiàn)在Linux下。這里我們只研究
Linux系統(tǒng)中的信號(hào)。默認(rèn)動(dòng)作:
Term:終止進(jìn)程
Ign: 忽略信號(hào) (默認(rèn)即時(shí)對(duì)該種信號(hào)忽略操作)
Core:終止進(jìn)程,生成Core文件。(查驗(yàn)進(jìn)程死亡原因, 用于gdb調(diào)試) Stop:停止(暫停)進(jìn)程
Cont:繼續(xù)運(yùn)行進(jìn)程
注意從man 7 signal幫助文檔中可看到 : The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.
這里特別強(qiáng)調(diào)了9) SIGKILL 和19) SIGSTOP信號(hào),不允許忽略和捕捉,只能執(zhí)行默認(rèn)動(dòng)作。甚至不能將其設(shè)置為阻塞。
1) SIGHUP: 當(dāng)用戶退出shell時(shí),由該shell啟動(dòng)的所有進(jìn)程將收到這個(gè)信號(hào),默認(rèn)動(dòng)作為終止進(jìn)程
2) SIGINT:當(dāng)用戶按下了組合鍵時(shí),用戶終端向正在運(yùn)行中的由該終端啟動(dòng)的程序發(fā)出此信號(hào)。默認(rèn)動(dòng)作為終止進(jìn)程。
3) SIGQUIT:當(dāng)用戶按下組合鍵時(shí)產(chǎn)生該信號(hào),用戶終端向正在運(yùn)行中的由該終端啟動(dòng)的程序發(fā)出些信號(hào)。默認(rèn)動(dòng)作為終止進(jìn)程.
4) SIGILL:CPU檢測(cè)到某進(jìn)程執(zhí)行了非法指令。默認(rèn)動(dòng)作為終止進(jìn)程并產(chǎn)生core文件
5) SIGTRAP:該信號(hào)由斷點(diǎn)指令或其他 trap指令產(chǎn)生。默認(rèn)動(dòng)作為終止里程 并產(chǎn)生core文件。
6) SIGABRT: 調(diào)用abort函數(shù)時(shí)產(chǎn)生該信號(hào)。默認(rèn)動(dòng)作為終止進(jìn)程并產(chǎn)生core文件。
7) SIGBUS:非法訪問(wèn)內(nèi)存地址,包括內(nèi)存對(duì)齊出錯(cuò),默認(rèn)動(dòng)作為終止進(jìn)程并產(chǎn)生core文件。
8) SIGFPE:在發(fā)生致命的運(yùn)算錯(cuò)誤時(shí)發(fā)出。不僅包括浮點(diǎn)運(yùn)算錯(cuò)誤,還包括溢出及除數(shù)為0等所有的算法錯(cuò)誤。默認(rèn)動(dòng)作為終止進(jìn)程并產(chǎn)生core文件。
9) SIGKILL:無(wú)條件終止進(jìn)程。本信號(hào)不能被忽略,處理和阻塞。默認(rèn)動(dòng)作為終止進(jìn)程。它向系統(tǒng)管理員提供了可以殺死任何進(jìn)程的方法。
10) SIGUSE1:用戶定義 的信號(hào)。即程序員可以在程序中定義并使用該信號(hào)。默認(rèn)動(dòng)作為終止進(jìn)程。
11) SIGSEGV:指示進(jìn)程進(jìn)行了無(wú)效內(nèi)存訪問(wèn)。默認(rèn)動(dòng)作為終止進(jìn)程并產(chǎn)生core文件。
12) SIGUSR2:另外一個(gè)用戶自定義信號(hào),程序員可以在程序中定義并使用該信號(hào)。默認(rèn)動(dòng)作為終止進(jìn)程。
13) SIGPIPE:Broken pipe向一個(gè)沒(méi)有讀端的管道寫(xiě)數(shù)據(jù)。默認(rèn)動(dòng)作為終止進(jìn)程。
14) SIGALRM: 定時(shí)器超時(shí),超時(shí)的時(shí)間 由系統(tǒng)調(diào)用alarm設(shè)置。默認(rèn)動(dòng)作為終止進(jìn)程。
15) SIGTERM:程序結(jié)束信號(hào),與SIGKILL不同的是,該信號(hào)可以被阻塞和終止。
通常用來(lái)要示程序正常退出。執(zhí)行shell命令Kill時(shí),缺省產(chǎn)生這個(gè)信號(hào)。默認(rèn)動(dòng)作為終止進(jìn)程。
16) SIGSTKFLT:Linux早期版本出現(xiàn)的信號(hào),現(xiàn)仍保留向后兼容。默認(rèn)動(dòng)作為終止進(jìn)程。
17) SIGCHLD:子進(jìn)程結(jié)束時(shí),父進(jìn)程會(huì)收到這個(gè)信號(hào)。默認(rèn)動(dòng)作為忽略這個(gè)信號(hào)。
18) SIGCONT:如果進(jìn)程已停止,則使其繼續(xù)運(yùn)行。默認(rèn)動(dòng)作為繼續(xù)/忽略。
19) SIGSTOP:停止進(jìn)程的執(zhí)行。信號(hào)不能被忽略,處理和阻塞。默認(rèn)動(dòng)作為暫停進(jìn)程。
20) SIGTSTP:停止終端交互進(jìn)程的運(yùn)行。按下組合鍵時(shí)發(fā)出這個(gè)信號(hào)。默認(rèn)動(dòng)作為暫停進(jìn)程。
21) SIGTTIN:后臺(tái)進(jìn)程讀終端控制臺(tái)。默認(rèn)動(dòng)作為暫停進(jìn)程。
22) SIGTTOU: 該信號(hào)類似于SIGTTIN,在后臺(tái)進(jìn)程要向終端輸出數(shù)據(jù)時(shí)發(fā)生。默認(rèn)動(dòng)作為暫停進(jìn)程。
23) SIGURG:套接字上有緊急數(shù)據(jù)時(shí),向當(dāng)前正在運(yùn)行的進(jìn)程發(fā)出些信號(hào),報(bào)告有緊急數(shù)據(jù)到達(dá)。如網(wǎng)絡(luò)帶外數(shù)據(jù)到達(dá),默認(rèn)動(dòng)作為忽略該信號(hào)。
24) SIGXCPU:進(jìn)程執(zhí)行時(shí)間超過(guò)了分配給該進(jìn)程的CPU時(shí)間 ,系統(tǒng)產(chǎn)生該信號(hào)并發(fā)送給該進(jìn)程。默認(rèn)動(dòng)作為終止進(jìn)程。
25) SIGXFSZ:超過(guò)文件的最大長(zhǎng)度設(shè)置。默認(rèn)動(dòng)作為終止進(jìn)程。
26) SIGVTALRM:虛擬時(shí)鐘超時(shí)時(shí)產(chǎn)生該信號(hào)。類似于SIGALRM,但是該信號(hào)只計(jì)算該進(jìn)程占用
CPU的使用時(shí)間。默認(rèn)動(dòng)作為終止進(jìn)程。
27) SGIPROF:類似于SIGVTALRM,它不公包括該進(jìn)程占用CPU時(shí)間還包括執(zhí)行系統(tǒng)調(diào)用時(shí)間。默認(rèn)動(dòng)作為終止進(jìn)程。
28) SIGWINCH:窗口變化大小時(shí)發(fā)出。默認(rèn)動(dòng)作為忽略該信號(hào)。
29) SIGIO:此信號(hào)向進(jìn)程指示發(fā)出了一個(gè)異步IO事件。默認(rèn)動(dòng)作為忽略。
30) SIGPWR:關(guān)機(jī)。默認(rèn)動(dòng)作為終止進(jìn)程。
31) SIGSYS:無(wú)效的系統(tǒng)調(diào)用。默認(rèn)動(dòng)作為終止進(jìn)程并產(chǎn)生core文件。
34) SIGRTMIN ~ (64) SIGRTMAX:LINUX的實(shí)時(shí)信號(hào),它們沒(méi)有固定的含義(可以由用戶自定義)。所有的實(shí)時(shí)信號(hào)的默認(rèn)動(dòng)作都為終止進(jìn)程。
終端按鍵產(chǎn)生信號(hào)
Ctrl + c → 2) SIGINT(終止/中斷) "INT" Interrupt
Ctrl + z → 20) SIGTSTP(暫停/停止) "T" ----Terminal 終端。 Ctrl + \ → 3) SIGQUIT(退出)
硬件異常產(chǎn)生信號(hào)
除0操作 → 8) SIGFPE (浮點(diǎn)數(shù)例外) "F" -----float 浮點(diǎn)數(shù)。非法訪問(wèn)內(nèi)存 → 11) SIGSEGV (段錯(cuò)誤)
總線錯(cuò)誤 → 7) SIGBUS