系統呼叫與訊號重啟,好

2021-09-07 09:33:44 字數 1791 閱讀 2281

這篇寫的很好

unix系統程式設計,這本書中有大量的重啟系統呼叫,例如下面的例子:選自p50,

pid_t r_wait(int *stat_loc)

還有對read,write的重啟操作。

unp volume1中提到slow system call,unp中的例子是accept系統呼叫,accept是伺服器端接受網路客戶端的連線,connect,將完成三次握手協議的連線返回。如果伺服器開啟了監聽listen,但是始終沒有客戶端來連線connect,可以想見,accept就阻塞在此。這是一種比較好理解的阻塞型系統呼叫。

wait也是一種阻塞性的呼叫。

但是linux世界上還有另外一種東東,叫做訊號,來處理突發事件。

一般來講,乙個系統呼叫,要麼成功,要麼失敗,但是由於為了及時處理訊號,出現了第三種情況,系統呼叫被訊號中斷,為了標識這種情況,錯誤碼errno置為eintr。

我們可以看到這種方式並不優美,程式設計師需要自己判斷errno,如果被訊號終端,那麼還需要自己來重啟系統呼叫。這是system v unix的實現方式。

bsd 核心想程式設計師之所想,急程式設計師之所急,採用了另外一種實現,就是如果中斷系統呼叫,切換到使用者態來執行訊號處理程式,那麼系統呼叫沒有返回值,核心在訊號處理函式結束後,自動重啟系統呼叫。這種方式很貼心阿,程式設計師再也不用自己判斷errno,然後重啟系統呼叫了。

linux不愧是unix世界的傑出新秀,他通過sa_restart 就可以支援bsd方案。

#include#include

#include

#include

#include

#include

pid_t r_wait(

int *stat_loc)

else

*/ }

return

ret;

}void

sig_alrm_func()

int main(int argc,char**ar**)

n = atoi(ar**[1

]);

act.sa_handler =sig_alrm_func;

sigemptyset(&act.sa_mask);

act.sa_flags = 0

;

|= sa_restart;

sigaction(sigalrm,&act,null);

for(i = 0;i)

if(childpid == 0

)

while(r_wait(null) >0

) ; fprintf(stderr,

"i :%d process id : %ld,\t parent id :%ld \tchild id : %ld\n",

i,(long)getpid(),(long)getppid(),(long

)childpid);

return0;

}

view code

原文中對比了三種方案。

第一種,是不判斷eintr.

第二種,是判斷eintr,然後重啟。

第三種,是對於訊號處理函式,sigaction,裡面sa_flags 加上對 sa_restart的支援,這樣被中斷的系統呼叫就能夠自動重啟了。

注意,和sleep是不一樣的。sleep是返回的秒數可能不足。

返回剩餘的秒數,而不是errno=eintr。

sleep的例子應該是,sigalarm,因為本身sleep就是用sigalarm實現的。

訊號與系統

匆忙整理,凌亂不堪。待補。的函式 功率訊號,週期平均的內積 r12 f1 t f2 t dt 延遲 比例 疊加 相乘sa t sinc t sin t t 是能量訊號 平方可積 不穩定系統 不絕對可積 週期訊號均可被表示為各種簡諧波的加權和 非週期訊號均可用簡諧波訊號的加權積分表示。週期訊號f t ...

訊號與系統

訊號 某些物理現象的行為或本質的資訊的 電路 中學習了實際電路的實現,分為 發生,使用,傳輸。那麼如何利用呢?現在將學習抽象上的訊號。電路有許多不同的實際應用 訊號 訊號的載體,需經處理提取資訊 表現形式為函式 波形圖 資訊 抽象地 包含的物理資訊 分類 是否能確定值 具有特別的規律 週期性 連續與...

system呼叫與SIGCHLD訊號

很多時候,我們需要通過system這個函式在程式內部來執行系統命令。比如 int rv system mount mnt hgfs 最近有同事發現system呼叫返回 1,但事實上外部命令已成功執行。經調查發現,原來是server在啟動後將自己設定為daemon時,遮蔽了sigchld訊號導致的。在...