unp-TCP客戶/服務(wù)器程序?qū)W習(xí)1

要點(diǎn):

1.服務(wù)器子進(jìn)程中止時,給父進(jìn)程發(fā)送一個 SIGCHLD信號,該信號默認(rèn)是被忽略,需要自己處理------信號處理

2.為了 可移植性,使用自己的 signal 函數(shù)。代碼如下:

#include"unp.h"

Sigfunc*

signal(int signo,Sigfunc*func)

{

struct sigaction act,oact;

act.sa_handler=func;

sigemptyset(&act.sa_mask);

act.sa_flags=0;

if(signo==SIGALM)

{

#ifdef SA_INTERRUPT

? ? ? ?act.sa_flags |=SA_INTERRUPT;

#endif

}else{

#ifdef SA_RESTART

act.sa_flags|=SA_RESTART;

#endif

}

if(sigaction(signo,&act,&oact)<0)

return(SIG_ERR);

return(oact.sa_handler);

}


}

}


附上sigaction的說明:

定義函數(shù) int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);

函數(shù)說明 sigaction()會依參數(shù)signum指定的信號編號來設(shè)置該信號的處理函數(shù)。參數(shù)signum可以指定SIGKILL和SIGSTOP以外的所有信號。

如參數(shù)結(jié)構(gòu)sigaction定義如下

struct sigaction {

void (*sa_handler)(int);

void (*sa_sigaction)(int, siginfo_t *, void *);

sigset_t sa_mask;

int sa_flags;

void (*sa_restorer)(void);

}

信號處理函數(shù)可以采用void (*sa_handler)(int)或void (*sa_sigaction)(int, siginfo_t *, void *)。到底采用哪個要看sa_flags中是否設(shè)置了SA_SIGINFO位,如果設(shè)置了就采用void (*sa_sigaction)(int, siginfo_t *, void *),此時可以向處理函數(shù)發(fā)送附加信息;默認(rèn)情況下采用void (*sa_handler)(int),此時只能向處理函數(shù)發(fā)送信號的數(shù)值。

sa_handler此參數(shù)和signal()的參數(shù)handler相同,代表新的信號處理函數(shù),其他意義請參考signal()。

sa_mask 用來設(shè)置在處理該信號時暫時將sa_mask 指定的信號集擱置。

sa_restorer 此參數(shù)沒有使用。

sa_flags 用來設(shè)置信號處理的其他相關(guān)操作,下列的數(shù)值可用。

sa_flags還可以設(shè)置其他標(biāo)志:

SA_RESETHAND:當(dāng)調(diào)用信號處理函數(shù)時,將信號的處理函數(shù)重置為缺省值SIG_DFL

SA_RESTART:如果信號中斷了進(jìn)程的某個系統(tǒng)調(diào)用,則系統(tǒng)自動啟動該系統(tǒng)調(diào)用

SA_NODEFER :一般情況下, 當(dāng)信號處理函數(shù)運(yùn)行時,內(nèi)核將阻塞該給定信號。但是如果設(shè)置了 SA_NODEFER標(biāo)記, 那么在該信號處理函數(shù)運(yùn)行時,內(nèi)核將不會阻塞該信號.

之后使用wait()/waitpid()處理以終止的子進(jìn)程。

void sig_chld(int signo)

{

pid_t pid;

int stat;

while((pid=waitpid(-1,&stat,WNOHANG))>0)

printf("child %d terminated\n",pid);

return ;

}

3.SIGCHLD信號是在父進(jìn)程阻塞在慢系統(tǒng)調(diào)用(accept)時由父進(jìn)程捕獲,內(nèi)核就會使accept返回EINTR錯誤(被中斷的系統(tǒng)調(diào)用),而不處理該錯誤,于是中止。因此需要自己處理。雖然有些系統(tǒng)提供SA_RESTART,但可移植性的方法更好。如下:

for( ?; ? ; ? ?)

{

? ? ? ? ? clilen=sizeof(cliaddr);

? ? ? ? ? if((connfd=accept(listenfd,(SA*)&cliaddr,&clilen))<0){

? ? ? ? ? ? ? if(errno==EINTR)

? ? ? ? ? ? ? continue;

? else

? ? err_sys("accept error");

}

注意:有一個函數(shù)不能重啟:connect.必須調(diào)用select來等待連接完成。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容