unp筆記二 多進程服務器

fork進程併發服務器範式

1、fork爲每一個客戶派生一個處理它們的子進程,子進程關閉監聽套接字,父進程關閉已連接套接字

listenfd=socket(...)
bind(listenfd,..)
listen(listenfd,..)
signal(SIGCHLD,sig_chld) //特意加上處理僵死進程,請看2
for(;;){
connfd=accept(listenfd,..) //在沒有新的連接來到時,父進程阻塞在此
if(fork()==0){
close(listenfd)  //子進程只負責連接,必須關了監聽套接字
doit(connfd)
close(connfd)
exit(0) //子進程結束前,關了connfd
}
close(connfd) //連接套接字有子進程負責,父進程關了它
}

2、按以上方式,肯定會產生僵死進程,必須處理僵死進程

服務器子進程終止時,給父進程發送一個SIGCHLD信號
SIGCHLD信號是由內核在任何一個進程終止時發給它的父進程的一個信號 內核發送給進程
所以我們在上面的僞代碼上加上SIGCHLD處理

這裏我們關注兩點,1、同時存在多個僵死子進程的情況,如何一個在處理一個信號的情況下,解決所有殘餘的僵死進程
2、SIGCHLD信號基本上是在父進程accept時收到的,怎樣處理被中斷的系統調用ACCEPT

SIGCHLD是不可靠信號,不排隊,處理方法是在一個循環內使用WAITPID 注意加參數WNOHANG

進程在accept阻塞時收到信號,如果內核無法自動重啓ACCEPT,則accept返回EINTR錯誤,我們只需要自己重啓ACCEPT就行,在代碼中查看errno==EINTR,然後重新accept;
實驗表明linux會自己重啓該系統調用,我們就可以不擔心這個問題,但是爲了我們的代碼在其他UNIX的操作系統也能很好地執行,最好把這個問題處理,就幾行代碼的事。


發佈了31 篇原創文章 · 獲贊 4 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章