天天看點

unp筆記二 多程序伺服器fork程序并發伺服器範式

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的作業系統也能很好地執行,最好把這個問題處理,就幾行代碼的事。