參考連線
乙個完整的訊號生命週期可以分為三個階段:
1. 訊號誕生
2. pcb中註冊
在程序表的表項中有乙個軟中斷訊號域,該域中每一位對應乙個訊號。核心給乙個程序傳送軟中斷訊號的方法,是在程序所在的程序表項的訊號域設定對應於該訊號的位;
如果訊號傳送給乙個正在睡眠的程序,如果程序睡眠在可被中斷的優先順序上,則喚醒程序;否則僅設定程序表中訊號域相應的位,而不喚醒程序。如果傳送給乙個處於可執行狀態的程序,則只置相應的域即可;
struct sigqueue
struct sigpending ;
訊號在程序中註冊指的就是訊號值加入到程序的未決訊號集sigset_t signal
中,並且訊號所攜帶的資訊被保留到未決訊號資訊鏈的某個sigqueue
結構中;
只要訊號在程序的未決訊號集中,表明程序已經知道這些訊號的存在,但還沒來得及處理或者該訊號被程序阻塞;
總之訊號註冊與否,與傳送訊號的函式如kill()
或sigqueue()
以及訊號安裝函式signal()
或sigaction()
無關,只與訊號值有關:
訊號值小於sigrtmin的訊號最多隻註冊一次,訊號值在sigrtmin及sigrtmax之間的訊號,只要被程序接收到就被註冊。
3. 訊號的執行和登出
核心處理乙個程序收到的軟中斷訊號是在該程序的上下文中,因此,程序必須處於執行狀態。當其由於被訊號喚醒或者正常排程重新獲得cpu時,在其從核心空間返回到使用者空間時會檢測是否有訊號等待處理。如果存在未決訊號等待處理且該訊號沒有被程序阻塞,則在執行相應的訊號處理函式前,程序會把訊號在未決訊號鏈中占有的結構卸掉:
當所有未被遮蔽的訊號都處理完畢後,即可返回使用者空間。
對於被遮蔽的訊號,當取消遮蔽後,在返回到使用者空間時會再次執行上述檢查處理的一套流程。
處理訊號的整個大概過程:
1. 程序由於系統呼叫或者中斷進入核心,完成相應任務返回使用者空間的前夕,檢查訊號佇列;
2. 如果有訊號,則根據訊號向量表找到訊號處理函式,設定好「frame」後,跳到使用者態執行訊號處理函式;
3. 訊號處理函式執行完畢後,返回核心態;
4. 設定「frame」,再返回到使用者態繼續執行程式;
5. 程序只有處理完訊號才會返回使用者態,程序在使用者態下不會有未處理完的訊號;
處理訊號有三種型別:
iii、幾點說明
當某個訊號的處理函式被呼叫時,核心自動將當前訊號加入程序的訊號遮蔽字,當訊號處理函式返回時自動恢復原來的訊號遮蔽字,這樣就保證了在處理某個訊號時,如果這種訊號再次產生,那麼它會被阻塞到當前處理結束為止。
如果要捕捉的訊號發生於程序正在乙個系統呼叫中時,並且該程序睡眠在可中斷的優先順序上(若系統呼叫未睡眠而是在執行,根據上面的分 析,等該系統呼叫執行完畢後再處理訊號),這時該訊號引起程序作一次longjmp,跳出睡眠狀態,返回使用者態並執行訊號處理例程。當從訊號處理例程返回時,程序就象從系統呼叫返回一樣,但返回了乙個錯誤如-1
,並將errno設定為eintr
,指出該次系統呼叫曾經被中斷。
若程序睡眠在可中斷的優先順序上,則當它收到乙個要忽略的訊號時,該程序被喚醒但不做longjmp,一般是繼續睡眠,但使用者感覺不到程序曾經被喚醒,而是象沒有發生過該訊號一樣; 若該訊號在阻塞訊號集中,在沒有解除阻塞之前不能忽略這個訊號, 因為程序仍有機會改變處理動作之後再解除阻塞。能夠使pause、sleep等函式從掛起態返回的訊號必須要有訊號處理函式,如果沒有什麼動作,可以將處理函式設為空。
block阻塞訊號對應阻塞訊號集,收到訊號集中的訊號不立即處理, 被阻塞的訊號將保持未決狀態,直到程序解除對此訊號的阻塞才執行抵達動作(可通過sigprocmask操作該訊號集)。
pending未決訊號對應未決訊號集, 表示還未被處理的訊號(可通過sigpending檢視)。
核心對子程序終止(sigcld)訊號的處理方法與其他訊號有所區別:
當程序正常或異常終止時,核心都向其父程序發乙個sigcld 訊號,預設情況下父程序忽略該訊號,就象沒有收到該訊號似的,如果父程序希望獲得子程序終止的狀態,則應該事先用signal函式為sigcld訊號設定訊號處理程式,在訊號處理程式中呼叫wait。sigcld訊號的作用是喚醒乙個睡眠在可被中斷優先順序上的程序。如果該程序捕捉了這個訊號,就象普通訊號處理一樣轉到處理例程。如果程序忽略該訊號,則什麼也不做。其實wait不一定放在訊號處理函式中,但這樣的話因為不知道子程序何時終止,在子程序終止前,wait將使父程序掛起休眠。
忽略sigchld訊號,這常用於linux併發伺服器的效能的乙個技巧因為併發伺服器常常fork很多子程序,子程序終結之後需要伺服器程序去wait清理資源。如果將此訊號的處理方式設為忽略,可讓核心把殭屍子程序轉交給init程序去處理,省去了大量殭屍程序占用系統資源。
我們需要捕獲sigpipe,或者忽略它,以防對端的close導致我們的程序被殺死。
iv、posix多執行緒與訊號
posix 1003.1 標準對多執行緒程式的訊號處理有更加嚴格的要求:
1. 多執行緒程式的所有執行緒應該共享訊號處理函式 , 但是每乙個執行緒必須有自己的阻塞訊號集和未決訊號集;
2. posix 介面kill( ), sigqueue( ) 必須把訊號發給執行緒組 , 而不是指定執行緒. 另外核心產生的sigchld, sigint, or sigquit 也必須發給執行緒組;
3. 執行緒組中只有有乙個執行緒來處理(deliver) 的共享的訊號就可以了;
4. 如果執行緒組收到乙個致命的訊號 , 核心要殺死執行緒組的所有執行緒, 而不是僅僅處理該訊號的執行緒;
linux訊號 阻塞訊號
1.訊號在核心中的表示 我們知道了訊號產生的各種原因,而實際執行訊號處理的動作,叫做訊號遞達 delivery 訊號從產生到遞達之間的狀態,稱為訊號未決 pending 程序可以選擇阻塞 block 某個訊號。被阻塞的訊號產生時將保持在未決狀態,直到程序解除對此訊號的阻塞,才執行遞達的動作。注意,阻...
Linux相關要點
linux下網路環境的配置 nat模式 子網ip 192.168.x.0 要與nat設定中的閘道器 192.168.x.1或192.168.x.2 保持一致。linux相關指令 pwd 獲取當前路徑 cd home目錄 cd 跳轉到當前目錄的子目錄 cd 返回上一級目錄 cd 跳轉到root根目錄 ...
Linux 使用要點
linux使用要點 修改超級管理員的密碼 sudo passwd 切換到超級管理員下 su su 使用者名稱 切換到指定使用者下 ls 列印當前目錄下的檔案及目錄 cd 路徑 切換當前路徑 clear 清理螢幕 ssh 用於遠端登入阿里雲 ssh 使用者名稱 ip ssh root 121.199....