上个博文说道,信号是在进程间通信的的一种方式。例如子进程执行结束后,向父进程发送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); } }