linux 訊號處理流程

2021-07-08 15:07:43 字數 3504 閱讀 5682

對於乙個完整的訊號生命週期(從訊號傳送到相應的處理函式執行完畢)來說,可以分為三個階段:

1    訊號誕生

這裡按發出訊號的原因簡單分類,以了解各種訊號:

(1) 與程序終止相關的訊號。當程序退出,或者子程序終止時,發出這類訊號。

(2) 與程序例外事件相關的訊號。如程序越界,或企圖寫乙個唯讀的記憶體區域(如程式正文區),或執行乙個特權指令及其他各種硬體錯誤。

(3) 與在系統呼叫期間遇到不可恢復條件相關的訊號。如執行系統呼叫exec時,原有資源已經釋放,而目前系統資源又已經耗盡。

(4) 與執行系統呼叫時遇到非**錯誤條件相關的訊號。如執行乙個並不存在的系統呼叫。

(5) 在使用者態下的程序發出的訊號。如程序呼叫系統呼叫kill向其他程序傳送訊號。

(6) 與終端互動相關的訊號。如使用者關閉乙個終端,或按下break鍵等情況。

(7) 跟蹤程序執行的訊號。

linux支援的訊號列表如下。很多訊號是與機器的體系結構相關的

訊號值 預設處理動作 發出訊號的原因

sighup 1 a 終端掛起或者控制程序終止

sigint 2 a 鍵盤中斷(如break鍵被按下)

sigquit 3 c 鍵盤的退出鍵被按下

sigill 4 c 非法指令

sigabrt 6 c 由abort(3)發出的退出指令

sigfpe 8 c 浮點異常

sigkill 9 aef kill訊號

sigsegv 11 c 無效的記憶體引用

sigpipe 13 a 管道破裂: 寫乙個沒有讀埠的管道

sigalrm 14 a 由alarm(2)發出的訊號

sigterm 15 a 終止訊號

sigusr1 30,10,16 a 使用者自定義訊號1

sigusr2 31,12,17 a 使用者自定義訊號2

sigchld 20,17,18 b 子程序結束訊號

sigcont 19,18,25 程序繼續(曾被停止的程序)

sigstop 17,19,23 def 終止程序

sigtstp 18,20,24 d 控制終端(tty)上按下停止鍵

sigttin 21,21,26 d 後台程序企圖從控制終端讀

sigttou 22,22,27 d 後台程序企圖從控制終端寫

處理動作一項中的字母含義如下

a 預設的動作是終止程序

b 預設的動作是忽略此訊號,將該訊號丟棄,不做處理

c 預設的動作是終止程序並進行核心映像轉儲(dump core),核心映像轉儲是指將程序資料在記憶體的映像和程序在核心結構中的部分內容以一定格式轉儲到檔案系統,並且程序退出執行,這樣做的好處是為程式設計師提供了方便,使得他們可以得到程序當時執行時的資料值,允許他們確定轉儲的原因,並且可以除錯他們的程式。

d 預設的動作是停止程序,進入停止狀況以後還能重新進行下去,一般是在除錯的過程中(例如ptrace系統呼叫)

e 訊號不能**獲

f 訊號不能被忽略

2 訊號在目標程序中註冊

在程序表的表項中有乙個軟中斷訊號域,該域中每一位對應乙個訊號。核心給乙個程序傳送軟中斷訊號的方法,是在程序所在的程序表項的訊號域設定對應於該訊號的位。如果訊號傳送給乙個正在睡眠的程序,如果程序睡眠在可被中斷的優先順序上,則喚醒程序;否則僅設定程序表中訊號域相應的位,而不喚醒程序。如果傳送給乙個處於可執行狀態的程序,則只置相應的域即可。

程序的task_struct結構中有關於本程序中未決訊號的資料成員: struct sigpending pending:

struct sigpending;

第三個成員是程序中所有未決訊號集,第

一、第二個成員分別指向乙個sigqueue型別的結構鏈(稱之為"未決訊號資訊鏈")的首尾,資訊鏈中的每個sigqueue結構刻畫乙個特定訊號所攜帶的資訊,並指向下乙個sigqueue結構:

struct sigqueue

訊號在程序中註冊指的就是訊號值加入到程序的未決訊號集sigset_t signal(每個訊號占用一位)中,並且訊號所攜帶的資訊被保留到未決訊號資訊鏈的某個sigqueue結構中。只要訊號在程序的未決訊號集中,表明程序已經知道這些訊號的存在,但還沒來得及處理,或者該訊號被程序阻塞。

當乙個實時訊號傳送給乙個程序時,不管該訊號是否已經在程序中註冊,都會被再註冊一次,因此,訊號不會丟失,因此,實時訊號又叫做"可靠訊號"。這意味著同乙個實時訊號可以在同乙個程序的未決訊號資訊鏈中占有多個sigqueue結構(程序每收到乙個實時訊號,都會為它分配乙個結構來登記該訊號資訊,並把該結構新增在未決訊號鏈尾,即所有誕生的實時訊號都會在目標程序中註冊)。

當乙個非實時訊號傳送給乙個程序時,如果該訊號已經在程序中註冊(通過sigset_t signal指示),則該訊號將被丟棄,造成訊號丟失。因此,非實時訊號又叫做"不可靠訊號"。這意味著同乙個非實時訊號在程序的未決訊號資訊鏈中,至多占有乙個sigqueue結構。

總之訊號註冊與否,與傳送訊號的函式(如kill()或sigqueue()等)以及訊號安裝函式(signal()及sigaction())無關,只與訊號值有關(訊號值小於sigrtmin的訊號最多隻註冊一次,訊號值在sigrtmin及sigrtmax之間的訊號,只要被程序接收到就被註冊)

3 訊號的執行和登出

核心處理乙個程序收到的軟中斷訊號是在該程序的上下文中,因此,程序必須處於執行狀態。當其由於被訊號喚醒或者正常排程重新獲得cpu時,在其從核心空間返回到使用者空間時會檢測是否有訊號等待處理。如果存在未決訊號等待處理且該訊號沒有被程序阻塞,則在執行相應的訊號處理函式前,程序會把訊號在未決訊號鏈中占有的結構卸掉。

對於非實時訊號來說,由於在未決訊號資訊鏈中最多隻占用乙個sigqueue結構,因此該結構被釋放後,應該把訊號在程序未決訊號集中刪除(訊號登出完畢);而對於實時訊號來說,可能在未決訊號資訊鏈中占用多個sigqueue結構,因此應該針對占用sigqueue結構的數目區別對待:如果只占用乙個sigqueue結構(程序只收到該訊號一次),則執行完相應的處理函式後應該把訊號在程序的未決訊號集中刪除(訊號登出完畢)。否則待該訊號的所有sigqueue處理完畢後再在程序的未決訊號集中刪除該訊號。

當所有未被遮蔽的訊號都處理完畢後,即可返回使用者空間。對於被遮蔽的訊號,當取消遮蔽後,在返回到使用者空間時會再次執行上述檢查處理的一套流程。

核心處理乙個程序收到的訊號的時機是在乙個程序從核心態返回使用者態時。所以,當乙個程序在核心態下執行時,軟中斷訊號並不立即起作用,要等到將返回使用者態時才處理。程序只有處理完訊號才會返回使用者態,程序在使用者態下不會有未處理完的訊號。

處理訊號有三種型別:程序接收到訊號後退出;程序忽略該訊號;程序收到訊號後執行使用者設定用系統呼叫signal的函式。當程序接收到乙個它忽略的訊號時,程序丟棄該訊號,就象沒有收到該訊號似的繼續執行。如果程序收到乙個要捕捉的訊號,那麼程序從核心態返回使用者態時執行使用者定義的函式。而且執行使用者定義的函式的方法很巧妙,核心是在使用者棧上建立乙個新的層,該層中將返回位址的值設定成使用者定義的處理函式的位址,這樣程序從核心返回彈出棧頂時就返回到使用者定義的函式處,從函式返回再彈出棧頂時,才返回原先進入核心的地方。這樣做的原因是使用者定義的處理函式不能且不允許在核心態下執行(如果使用者定義的函式在核心態下執行的話,使用者就可以獲得任何許可權)。

GLONASS訊號處理流程總結

glonass訊號雖然是fdma調製,但是在經過fpga降到中頻後,其捕獲過程需要進行相應調節,完成捕獲後轉入跟蹤模組,其跟蹤環路與gps bds無任何區別,可以參照實現。接下來重點介紹的是其位同步與幀同步的實現過程。由於glonass的乙個資料位元持續時間為20ms,但是上面調製了乙個明德碼,如下...

Linux 訊號處理

用sigcation函式 在標頭檔案signal.h中 來設定自己的訊號處理函式,用法參見 各種訊號參見 寫了個sigint,也就是c c鍵的處理例子 include includestruct sigaction newsigint,oldsigint void signalinthandler ...

linux 訊號處理

linux下的程式,有時候需要在接到一些終止訊號後,進行清理工作再退出。訊號2的處理函式 void signalhandler 2 int signal cleanup exit 2 int main int argc,char argv 處理訊號2 struct sigaction act 2,a...