上個博文說道,信號是在進程間通信的的一種方式。例如子進程執行結束後,向父進程發送sigchld信號,父進程就經過捕獲這個信號,就能夠對子進程的資源進行回收,避免其成爲殭屍進程。 git
進程間通訊的另一種方式是管道,主要是在父子進程間。父進程經過創立一個管道,fork()出子進程後,子進程繼承父進程的管道,從而,父子進程就造成了管道的兩端,從而能夠靠這兩端,進行父子進程之間的通訊。 服務器
建立管道 dom
建立管道的方法主要有兩種,一種是pipe函數,能夠man一下,解釋很清晰的;另一種是socketpair函數。前者建立的管道是半雙工的,後者的是全雙工的。 socket
下面是一個父子進程間通信的一個小例子。鏈接見http://git.oschina.net/mengqingxi89/codelittle/blob/master/codes/echoserver/ipc_shared_talker.cpp 函數
例子中有個小問題沒有解決,就是父進程往管道里寫數據,若是寫的過快的話,致使子進程沒有接到。因此我讓父進程寫一句,sleep(1),而後再寫。這樣,子進程就都收到了。我想,多是管道沒有存儲的功能?多寫的話,就寫不進去了。不知道。 .net
進程間通信的另外一個方式是共享內存。這個,我要在下面的聊天室程序裏介紹,這裏就沒介紹了。 code
#include"head.h" #define MAX_USER 1024 #define MAX_PROCESS 65535 #define BUF_SIZE 1024 typedef struct user { int conn; int stop; sockaddr_in client_addr; char bufread[BUF_SIZE]; char bufwrite[BUF_SIZE]; int pipefd[2]; //用來創建管道,一端是父進程,一端是子進程。 } user; typedef struct subprocessData { user* u; pid_t pid; pid_t ppid; }subprocessData; subprocessData subprocess[MAX_PROCESS]; /*子進程從父進程那裏讀取內容*/ int dowork_comm_with_father(user curuser) { curuser.stop=0; //子進程關閉寫端 close(curuser.pipefd[1]); setnonblock(curuser.pipefd[0]); while(!curuser.stop ) { int readn=read(curuser.pipefd[0],curuser.bufread,BUF_SIZE); if( (readn<0) && (errno!=EAGAIN)) { printf("a\n"); printf("read fail, client "); close(curuser.pipefd[0]); curuser.stop=1; } else if (readn==0) { printf("father close the pipe\n"); close(curuser.pipefd[0]); curuser.stop=1; } else if (readn>0) { printf("pid= %d\n",getpid()); curuser.bufread[readn]='\0'; printf("read from the father\n"); printf("%s\n",curuser.bufread); int writen=write(1,curuser.bufwrite,sizeof(curuser.bufwrite)); memset(curuser.bufread,0,sizeof(curuser.bufread)); } } } int main(int argc, char **argv) { printf("start server...\n"); /*服務器服務啓動,等待客戶端的連接的到來*/ int run_flag=1; user users[MAX_USER]; int user_number=0; /*這個pipe函數是簡單的建立管道的版本,他建立的管道,pipefd[0]只能讀,pipefd[1]只能寫*/ int fdret=pipe(users[user_number].pipefd); assert(fdret>=0); pid_t pid=fork(); if(pid<0) { printf("fork error\n"); exit(0); } else if (pid==0) { dowork_comm_with_father(users[user_number]); } /*parent process*/ else { /*在父進程中向子進程寫一些random內容*/ printf("pid=%d in parent\n",pid); subprocess[pid].u=&users[user_number]; close(users[user_number].conn); //父進程關閉管道的讀端,只往子進程寫內容 close(users[user_number].pipefd[0]); int write_times=5; for(int i=0;i<write_times;i++) { char buf[100]="hello from parent at time "; char bufwrite[100]; sprintf(bufwrite,"%s",buf); sprintf(bufwrite," %d\n",time(NULL)); write(users[user_number].pipefd[1],bufwrite,sizeof(bufwrite)); sleep(1); } printf("parent write over\n"); int stat_loc; /*若是想要多個進程共同服務的話,就不能在這裏阻塞的等待,能夠經過sigchld信號進行捕獲,見信號handler*/ // wait((int *)&stat_loc); printf("parent, finished wait\n"); // sleep(3); } }