當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > Linux信號基礎(chǔ)
一、信號使用基礎(chǔ)知識
1.信號的發(fā)送與捕捉:
同步:
多個(gè)進(jìn)程協(xié)同完成一件事情,當(dāng)資源不可用時(shí),其他的進(jìn)程阻塞等待,類比流水線操作,一步一步有先后地完成一個(gè)產(chǎn)品。
異步:
多個(gè)進(jìn)程做多項(xiàng)任務(wù),同時(shí)運(yùn)行,互不干擾,當(dāng)需要建立聯(lián)系的時(shí)候,停止運(yùn)行,建立聯(lián)系,處理數(shù)據(jù),處理完成繼續(xù)各自運(yùn)行。異步多個(gè)進(jìn)程或線程獨(dú)自運(yùn)行,效率較高,系統(tǒng)的實(shí)時(shí)性用中斷實(shí)現(xiàn)。
信號:
內(nèi)核和用戶空間溝通的信使。直接進(jìn)行用戶空間進(jìn)程和內(nèi)核進(jìn)程之間的交互,內(nèi)核進(jìn)程也可以利用它來通知用戶空間進(jìn)程發(fā)生了哪些系統(tǒng)事件。
eg:
進(jìn)程結(jié)束時(shí),內(nèi)核會(huì)發(fā)送一個(gè)SIGCHLD信號以通知父進(jìn)程子進(jìn)程結(jié)束。內(nèi)核向用戶發(fā)送信號時(shí),用戶進(jìn)程可以進(jìn)程阻塞。就像項(xiàng)目不能因?yàn)橐粋(gè)無名信號出錯(cuò)而結(jié)束進(jìn)程。
________________________________________
2.信號的周期:
紅色中的的內(nèi)容都是內(nèi)核操作,與用戶程序無關(guān),用戶程序就是信號處理。
信號由內(nèi)核產(chǎn)生,要由用戶空間進(jìn)行注冊和注銷。信號處理是定義的處理方式,相當(dāng)于內(nèi)核到用戶的一次切換。
用戶的處理方式有三種:
1)忽略
不理踩,有兩個(gè)信號不可以忽略(KILL和STOP信號);
2)捕捉
捕捉信號后,自定義處理方式,(用signal()進(jìn)行注冊);
3)默認(rèn)
系統(tǒng)默認(rèn)處理方式。
________________________________________
3.信號處理流程:
PS:
實(shí)際執(zhí)行信號的處理動(dòng)作稱為信號投遞(Delivery),信號從發(fā)生到投遞之間的狀態(tài),稱為信號未決(Pending)。
進(jìn)程可以選擇阻塞(Block)某個(gè)信號。被阻塞的信號產(chǎn)生后將保持在未決狀態(tài),直到進(jìn)程解除對此信號的阻塞,才執(zhí)行投遞的動(dòng)作。
每個(gè)信號都有兩個(gè)標(biāo)志位分別表示阻塞和未決,還有一個(gè)函數(shù)指針表示處理動(dòng)作。
信號產(chǎn)生時(shí),內(nèi)核在進(jìn)程控制塊中設(shè)置該信號的未決標(biāo)志(表示某信號是否發(fā)生過),直到信號投遞完畢才清除該標(biāo)志。在上圖的例子中,
1. SIGHUP信號未阻塞也未產(chǎn)生過,當(dāng)它遞達(dá)時(shí)執(zhí)行默認(rèn)處理動(dòng)作。
2. SIGINT信號產(chǎn)生過,但正在被阻塞,所以暫時(shí)不能投遞。雖然它的處理動(dòng)作是忽略,但在沒有解除阻塞之前不能忽略這個(gè)信號,因?yàn)檫M(jìn)程仍有機(jī)會(huì)改變處理動(dòng)作之后再解除阻塞。
3. SIGQUIT信號未產(chǎn)生過,一旦產(chǎn)生SIGQUIT信號將被阻塞,它的處理動(dòng)作是用戶自定義函數(shù)sighandler。
未決和阻塞標(biāo)志可以用相同的數(shù)據(jù)類型sigset_t來存儲(chǔ),sigset_t稱為信號集,這個(gè)類型可以表示每個(gè)信號的“有效”或“無效”狀態(tài),在阻塞信號集中“有效”和“無效”的含義是該信號是否被阻塞,而在未決信號集中“有效”和“無效”的含義是該信號是否處于未決狀態(tài)。
________________________________________
4.信號應(yīng)用的場合:
________________________________________
5.常用的幾種信號與默認(rèn)方式:
SIGALRM定時(shí)信號,定時(shí)N秒,時(shí)間到,發(fā)送一個(gè)鬧鐘信號,終止進(jìn)程。
對信號的處理方式解釋:
1)忽略此信號
除了兩種信號(SIGKILL和SIGSTOP)不能被忽略外,其它的的信號都可被忽略,這兩個(gè)信號不能被忽略的原因是:它們提供一種終極的終止或停止進(jìn)程的可靠方法,這是一種終極裁判權(quán),如果這兩個(gè)信號都被忽略了的話,某個(gè)進(jìn)程跑飛后就沒有辦法終止或停止這個(gè)進(jìn)程。
另外忽略某些硬件產(chǎn)生的信號被認(rèn)為是不可取的,如我們?nèi)绻雎苑欠ù鎯?chǔ)訪問或除以0等硬件產(chǎn)生的信號的話,進(jìn)程狀態(tài)未定義的(無法確定的狀態(tài))。
2)捕獲信號
如果某個(gè)進(jìn)程被通知某個(gè)信號發(fā)生了,但是想要捕獲這個(gè)信號的話,該進(jìn)程就必須向內(nèi)核注冊一個(gè)捕獲函數(shù),當(dāng)相應(yīng)的信號發(fā)生時(shí),捕獲函數(shù)就會(huì)被調(diào)用并執(zhí)行希望對這個(gè)事件的處理。
3)執(zhí)行系統(tǒng)的默認(rèn)操作
其實(shí)我們內(nèi)核為每個(gè)信號在發(fā)生時(shí)都規(guī)定了一個(gè)默認(rèn)的操作,如果我們不捕獲也不忽略的話,當(dāng)這個(gè)信號發(fā)生時(shí),進(jìn)程會(huì)按照默認(rèn)方式去處理這些發(fā)生的信號,當(dāng)然對于絕大多數(shù)信號而言,其默認(rèn)的處理方式都是終止接收到該信號的進(jìn)程或者忽略此信號。
/**************************************************************************拓展:
查看信號的方法:
kill -l 或man 7 signal
通常有62以上,kill -l 列出的前面32個(gè)是非實(shí)時(shí)的,signal函數(shù)只能使用前( 1 -- 31),后面為拓展信號,signal不能用,中間缺少的沒有編號。前面(1 -- 31)是非實(shí)時(shí)的,信號不支持排隊(duì),可能造成信號丟失。有預(yù)定義的含義和處理方式函數(shù)。后面的實(shí)時(shí)信號支持排隊(duì)
各種信號說明:
//www.2cto.com/os/201608/537204.html (感謝博主詳細(xì)列出了各種信號)
***************************************************************************/
我們常用的有:
INT, QUIT, KILL, USR1, USR2 ALRM STOP TERM .
USR1,和USR2在硬件中沒有任何價(jià)值,在應(yīng)用程序中,可以使用usr1和usr2進(jìn)行自定義通信。
TTOU/TTIN網(wǎng)絡(luò)開發(fā)中常用的信號,IO信號在網(wǎng)路常用。
________________________________________
二、相關(guān)系統(tǒng)調(diào)用:
1.kill()和raise()
pid = -1,向所有進(jìn)程發(fā)送信號(除了init進(jìn)程)。
sig = 0;表示只檢查錯(cuò)誤信息,不發(fā)送信號。沒有0號編號信號。
kill示例:
raise示例:
當(dāng)前進(jìn)程進(jìn)入stop態(tài),發(fā)送CONT信號繼續(xù)運(yùn)行。如果發(fā)送的是USR1信號,默認(rèn)進(jìn)程退出。
________________________________________
2.a(chǎn)larm()和pause()
0.alarm是指定一定時(shí)間后發(fā)送信號。
1.要注意的是,一個(gè)進(jìn)程只能有一個(gè)鬧鐘時(shí)間。如果在調(diào)用alarm時(shí)已設(shè)置過鬧鐘時(shí)間,則之前的鬧鐘時(shí)間被新值所代替。
2.alarm函數(shù)只設(shè)置時(shí)鐘,設(shè)置完成后,程序向下繼續(xù)運(yùn)行。(補(bǔ)充說明alarm函數(shù)只是設(shè)置定時(shí)鬧鐘,并不阻塞);
3.等待信號來臨可以利用while檢測等待或利用pause函數(shù)將進(jìn)程掛起。
pause()接收任意信號就會(huì)結(jié)束掛起。
示例代碼: myalarm.c
mypause.c
利用alarm和pause實(shí)現(xiàn)sleep功能:
補(bǔ)充:
alarm()和sleep()函數(shù)不同,alarm信號并不會(huì)阻塞,相當(dāng)于訂了鬧鐘后,系統(tǒng)在后臺(tái)計(jì)時(shí),到了指定時(shí)間就會(huì)發(fā)送ALRM信號;sleep()函數(shù)會(huì)使進(jìn)程進(jìn)入睡眠態(tài),進(jìn)程暫停執(zhí)行,直到時(shí)間結(jié)束。