若是邏輯控制流在時間上是重疊的,那麼它們就是併發的,能夠出如今計算機系統的不一樣層面上,硬件異常處理程序、進程和Unix信號處理程序都是併發的。併發能夠看做是操做系統內核用來運行多個應用程序的機制,可是併發不侷限於內核。它也能夠在應用程序中扮演角色。併發的主要做用有:訪問慢速IO設備;與人交互的程序;經過推遲工做以下降延遲;服務多個網絡客戶端的請求。併發一般能夠有三種,基於進程、基於IO多路複用、基於線程。 服務器
進程是一個程序運行的實例。每個進程都有本身獨立的地址空間,通常狀況下,包括文本區域、數據區域和堆棧。文本區域是存儲處理器執行的代碼;數據區域存儲變量和線程執行期間使用的動態分配的內存;堆棧區域存儲着活動過程調用的指令和本地變量。程序是一個沒有生命的實體,只有處理器賦予程序生命,而後由操做系統去執行它,它才能稱做一個實體,稱爲進程。 網絡
一個併發服務器的天然構造方法是,在父進程中接受客戶端的鏈接請求,而後建立一個子進程來爲每一個新客戶端提供服務。在鏈接接受請求以後,服務器派生一個子進程,這個子進程獲取服務器描述符表的完整拷貝,子進程關閉它的拷貝的監聽描述符,而父進程關閉它的已鏈接描述符,不然,將永遠不會釋放已鏈接描述符的文件表條目,並且由此引起的存儲器泄露將最終消耗盡可用的服務器,使系統崩潰。 併發
對於父、子進程間共享狀態信息,進程有一個很是清晰的模型:共享文件表,可是不共享用戶地址空間。進程有獨立的地址空間既是優勢,也是缺點,這樣一來,一個進程不可能不當心覆蓋另外一個進程的虛擬存儲器;另外一方面,獨立的地址空間使得進程之間共享信息變得更加困難。另外,基於進程的設計另外一個缺點是,每每運行比較慢,由於進程控制和IPC開銷比較高。 app
本程序在Unix 環境下用C語言開發的,而且調用了csapp.h的現成頭文件。 函數
//本程序是一個基於多進程的併發echo服務器,父進程派生一個子進程來處理每一個新的鏈接請求 #include "csapp.h" //echo程序,用於向客戶端發送響應主體 void echo(int connfd) { int n; char buf[MAXLINE]; rio_t rio; rio_readinitb(&rio,connfd); //帶緩衝的讀取函數 while((n=rio_readlineb(&rio,buf,MAXLINE))>0) { //向鏈接符寫入內容 printf("server received %d bytes \n",n); rio_writen(connfd,buf,n); } } //信號處理函數,用於處理僵死進程,即回收已經終止的進程給系統帶來的資源佔用 void sigchld_handler(int sig) { //-1表明回收父進程的子進程組,因爲unix信號是不排隊的,所以必須準備好回收多個僵死子進程的準備 while(waitpid(-1,0,WNOHANG)>0) ; return; } int main(int argc,char **argv) { int listenfd,connfd,port; socklen_t clientlen=sizeof(struct sockaddr_in); struct sockaddr_in clientaddr; if(argc!=2) { fprintf(stderr,"usage :%s <port>\n",argv[0]); exit(0); } //將字符串轉化爲整型,端口號 port=atoi(argv[1]); //啓動信號處理函數監聽器 signal(SIGCHLD,sigchld_handler); //啓動服務器監聽描述符 listenfd=open_listenfd(port); while(1) { //已鏈接描述符,接受鏈接 connfd=accept(listenfd,(SA *)&clientaddr,&clientlen); //開闢子進程,用於處理鏈接請求 if(fork()==0) { //因爲子進程共享父進程的全部資源,所以先關閉監聽描述符,再調用請求體命令,而後關閉已鏈接描述符,而且正常終止此進程 close(listenfd); echo(connfd); close(connfd); exit(0); } //關閉父進程的已鏈接描述符 close(connfd); } }使用telnet來測試程序:
zzw@zzw-ThinkPad-Edge-E430c:~$ telnet localhost 8080 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. hello hello
root@zzw-ThinkPad-Edge-E430c:/home/zzw/doc_main/CProgram/Concurrency# ./echoserverp.o 8080 server received 7 bytes