這篇寫的很好
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#includeview code#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;
}
原文中對比了三種方案。
第一種,是不判斷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訊號導致的。在...