Linux通訊之訊號

2021-10-08 19:29:05 字數 3623 閱讀 7801

a給b傳送訊號,b收到訊號之前執行自己的**,收到訊號之後,不管執行到程式的什麼位置,都要暫停執行,去處理訊號,處理完畢再繼續執行。與硬體中斷類似——非同步模式。但訊號是軟體層面上實現的中斷,早期常被稱為"軟中斷"。

訊號的特質:由於訊號是通過軟體方法實現,其實現手段導致訊號有很強的延時性。但對於使用者來說,這個延時時間非常短,不易察覺。

每個程序所收到的所有訊號,都是由核心負責傳送的,核心處理

按鍵產生,如:ctrl+c、ctrl+z、ctrl+\

系統呼叫產生,如:kill、raise、abort

軟體條件產生,如:定時器 alarm

硬體異常產生,如:非法訪問記憶體(段錯誤)、除0(浮點數例外)、記憶體對齊出錯(匯流排錯誤)

命令產生,如:kill 命令

執行預設動作

忽略(丟棄)

捕捉(該使用者處理函式)

linux核心的程序控制塊 pcb 是乙個結構體,task_struct,除了包含程序id,狀態,工作目錄,使用者id,組id,檔案描述符表,還包含了訊號相關的資訊,主要指阻塞訊號集和未決訊號集。

訊號產生,未決訊號集 中描述該訊號的位立刻翻轉為1,表示該訊號處於未決狀態,當訊號被處理,對應位翻轉回0.這一時刻往往非常短暫。

訊號產生後由於某些原因(主要是阻塞)不能抵達。這類訊號的集合稱之為未決訊號集。在遮蔽解除前,訊號一直處於未決狀態。

與變數三要素類似的,每個訊號也有其必備的4要素,分別是:

編號 2. 名稱 3. 事件 4. 預設處理動作

可通過 man 7 signal 檢視幫助文件獲取

1. 終端按鍵產生的訊號
ctrl + c-->(2)sigint(終止/中斷) int(中斷)

ctrl + z-->(20)sigtstp(暫停/停止) t(終端)

ctrl + \-->(3)sigquit(退出)

2. 硬體異常產生的訊號
3. kill函式/命令產生訊號
int kill(pid_t pid, int sig);成功:0; 失敗:-1(id非法,訊號非法,普通使用者殺init程序等權級問題),設定 errno

sig:不推薦直接使用數字,用使用巨集名,因為不同os訊號編號可能不同,但名稱一致

pid > 0:傳送訊號給指定程序

pid = 0:傳送訊號給呼叫kill函式程序屬於同一程序組的所有程序

pid < 0:取 |pid| 傳送給對應程序組

pid = -1:傳送給程序有許可權傳送的系統中所有程序

【程序組】每個程序都屬於乙個程序組,程序組是乙個或多個程序的集合,它們相互關聯,共同完成乙個實體任務,每個程序都有乙個程序組長,預設程序組id與程序組長id相同

4. raise 和 abort 函式
5. 軟體條件產生訊號
alarm 函式

設定定時器(鬧鐘)。在指定 seconds 後,核心會給當前程序傳送(14)sigalrm訊號。程序收到該訊號,預設動作終止

每個程序都有且只有唯一乙個定時器

unsigned int alarm(unsigned int seconds);返回0或剩餘的秒數,無失敗

常用:取消定時器 alarm(0),返回舊鬧鐘餘下秒數

【定時】:與程序狀態無關(自然定時法)!就緒、執行、掛起(阻塞、暫停)、終止、殭屍……無論處於何種狀態,alarm 都計時

【練習】:編寫程式,測試你使用的計算機 1 秒鐘能數多少個數

#include

#include

intmain()

return0;

}

【執行結果】

使用 time 命令檢視程式執行的時間。

real:程式實際執行的時間

user:程式在使用者空間執行的時間

sys:程式在核心中執行的時間

實際執行時間 = 系統時間 + 使用者時間 + 等待時間

從執行結果看出,user + sys 相加的時間遠遠小於程式實際執行的時間,那麼該程式大部分時間都在等待,程式主要是在等待硬體,因為需要往控制台上輸出,會消耗時間,如果直接往檔案中寫入(./alarm > out),那麼效率就會很高了

這時候可以看出 user + sys 的時間與實際執行的時間很接近了。所以我們可以得出乙個結論:程式執行的瓶頸在於io,優化程式,首選優化io

setirimer 函式

設定定時器(鬧鐘),可代替 alarm 函式。精度微妙 us,可以實現週期定時

int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);

【返回值】成功:0;失敗:-1,設定 errno

【引數】:which

自然定時:itimer_real -> (14)sigarm 計算自然時間

虛擬空間計時(使用者空間):itimer_virtual -> (26)si**talrm 只計算程序占用 cpu 的時間

執行時計時(使用者+核心):itimer_prof -> (27)sigprof 計算占用cpu及執行系統呼叫的時間

【練習】使用setitimer函式實現 alarm 函式,重複計算機 1 秒數數程式

#include

#include

#include

intmain()

return0;

}

【執行結果】

Linux通訊之訊號(二)

訊號捕捉 訊號捕捉特性 核心實現訊號捕捉過程 核心通過讀取未決訊號集來判斷訊號是否應被處理,訊號遮蔽字 mask 可以影響未決訊號集。而我們可以在應用程式中自定義 set 來改變 mask。以達到遮蔽指定訊號的目的。sigset t set typedef unsigned long sigset ...

linux之通訊之訊號學習1

比如我們按下了鍵盤或者其它硬體故障 軟體 最常用傳送訊號的系統函式是kill,raise,alarm 和setitimer 以及sigqueue 函式,軟體 還包括一些非法運算等操作。程序可以通過三種方式來響應乙個訊號 1 忽略訊號,即對訊號不做任何處理,其中,有兩個訊號不能忽略 sigkill 及...

linux程序間通訊之訊號

1 wait 函式 原型 pid t wait int status 子程序退出時,它向父程序傳送乙個sigchld訊號,預設情況是總是忽略sigchld訊號,此時程序狀態一直保留在記憶體中,因此需要父程序去處理改訊號,處理的辦法則是呼叫wait 函式,收集子程序狀態資訊,並清空該資訊 使用wait...