引言:上篇文章講到同步阻塞迭代式的進程方式,這篇文章講述一下關於處理單進程阻塞於系統調用的情況。使用方式是多進程的方式,可以減少很大一部分的因為進程阻塞所帶來的服務器無法響應問題。
基本思想是這樣,如上篇文章所述,在單進程阻塞在read() 系統調用的時候,會導致服務器無法響應其他的連接請求,那么我們可以通過在服務器fork() 出很多子進程來處理業務,而主進程負責 accept() 其他的客戶連接。
主體框架是這樣:
for(;;){ fd = accept(...); ret = fork() ; switch( ret ) { case -1 : do_err_handler(); break; case 0 : // 子進程 do_handler_fd( fd ); break ; default : // 父進程 continue ; } }
總體來說,符合上述所說的,主進程負責 accept() 連接,子進程處理連接。
當然,在do_handler_fd(fd) 中,可以關閉監聽套接口等,只負責處理連接套接口。處理過程也是和上一章所說的一樣。
read(fd,buf,n); dosomething(buf); write(fd,buf,n);
在父進程中需要設置信號處理函數,用來處理子進程退出時候產生的 SIG_CHLD型號,信號處理函數中調用 wait() 。避免產生僵屍進程、
我們來比較一下這個模型和前一個同步阻塞迭代式:
(1)並發量:這里的服務器主進程不再阻塞於read或者write()系統調用,而是通過子進程完成業務處理。阻塞也只是阻塞在子進程中。那么可以減輕服務器主進程的相應時間要求。並發量大大加強,但是會受到操作系統的限制。
(2)代碼復雜度:越到后面的代碼復雜度肯定越高,開發難度也會慢慢加強。
(3)穩定性:服務器的穩定性現在兩個版本還沒有體現出來。不過如果沒有處理好進程之間的協作和並發控制等第二個版本還是會比第一個版本稍微顯得不穩定。
多進程還有另一種方式Pre-fork方式,也就是進程池方式,這里沒有做過多的介紹,以后會加上這部分內容。
總結:說一下多進程並發式的服務器端模型的好處就是,主進程不用阻塞在IO系統調用中,而專注於負責處理連接請求。但是,進程本身的開銷是很大的,頻繁的創建進程會消耗很多務器端的資源。所以,還有其他的處理方式,那就是線程模型。既然創建多進程消耗系統資源,我們可以采取采用線程的方式來達到目的。這就是下一篇文章要談論的:多線程方式(會有一個線程池的實例)