进程之间是独立的,但是又是有联系的,他们可以使用管道、信号、socket、消息队列和共享内存来实现通信,那么我们先来看看进程之间如何使用管道:
-
- #include<stdio.h>
- #include<stdlib.h>
- #include<unistd.h>
- #include<string.h>
- #include<sys/types.h>
- #include<sys/wait.h>
- int main()
- {
-
- pid_t pid;
- int fd[2];
- int ret=pipe(fd);
- if(ret==-1)
- {
- printf("pipe error!\n");
- exit(1);
- }
- pid=fork();
- if(pid==-1)
- {
- perror("fork error\n");
- exit(1);
- }
- else if(pid>0)
- {
- waitpid(pid,NULL,WNOHANG);
- close(fd[1]);
- char buf[1024]={0};
- int len=0;
- len=read(fd[0],buf,sizeof(buf));
- printf("parent receive meassge:%s\n",buf);
- close(fd[0]);
- sleep(2);
- }
- else if(pid==0)
- {
-
- close(0);
- char * str="this is a message by child send!\n";
- write(fd[1],str,strlen(str)+1);
- close(fd[1]);
- sleep(2);
-
-
- }
- return 0;
- }
-
要注意几个点,管道是需要在进程创建之前在再创建的,如果在进程之后创建管道的话顺序就乱了,管道将不会生效,而且这个半双工过程,也就说我们一次只能通信一次,要么是a向b发信息,要么就是b向a,不能ab同时,所以我这里就拿父子进程来讲解;
首先我们创建管道(pipe函数):
- int fd[2];
- int ret=pipe(fd);
他需要一个int数组,两个元素,一个是读端(fd[0])一个是写端(fd[1]),pipe这个函数就是用来创建管道的,他的参数就是这个数组;
- close(fd[1]);
- char buf[1024]={0};
- int len=0;
- len=read(fd[0],buf,sizeof(buf));
- printf("parent receive meassge:%s\n",buf);
- close(fd[0]);
- sleep(2);
在我们要写或者读一个内容的时候,如果是写我们就应该把读的管道描述符关闭,也就是这里的fd[0],同理如果是读的话就是关闭写了;
使用读写流也是read和write之前我讲过的,参数的话第一个就是描述符,第二个就是数据,第三个就是长度,这里注意read的返回值是读取到的真实长度,如果读取失败的话就是返回-1;如果想要父子之间一直保持通讯的话我们就不能关闭读写流了:
- #include<stdio.h>
- #include<stdlib.h>
- #include<unistd.h>
- #include<string.h>
- #include<sys/types.h>
- #include<sys/wait.h>
- int main()
- {
-
- pid_t pid;
- int fd[2];
- int ret=pipe(fd);
- if(ret==-1)
- {
- printf("pipe error!\n");
- exit(1);
- }
- pid=fork();
- if(pid==-1)
- {
- perror("fork error\n");
- exit(1);
- }
- else if(pid>0)
- {
- char buf[1024]={0};
- while(1)
- {
- waitpid(pid,NULL,WNOHANG);
- int len=0;
- len=read(fd[0],buf,sizeof(buf));
- printf("parent receive meassge:%s\n",buf);
- sleep(2);
- char * str = "fighing ,child ,you are my hope!\n";
- write(fd[1],str,strlen(str)+1);
- sleep(2);
- }
- }
- else if(pid==0)
-
- {
- char buf[1024]={0};
- while(1)
- {
- char * str="fighting , parent , you are my example!\n";
- write(fd[1],str,strlen(str)+1);
- sleep(2);
- int len=0;
- len = read(fd[0],buf,sizeof(buf));
- sleep(2);
- printf("child receive message:%s\n",buf);
- }
-
- }
- return 0;
- }
-
父子进程之间通讯要注意:
1、要先创建管道,再创建进程;2、父子进程要互相读写数据的时候就不需要关闭读写端,卡好时间即可;
匿名管道的含义:
匿名管道就是类似于 ls | wc –l这种由| 连接的一个或者多个命令,|的前一个命令的输出会作为后一个命令的输入;
父子之间通讯是共用一个管道,管道的两端只能进行读写操作中的一种,因此父子通讯时应该关闭父子进程中的一个文件描述符,比如在父进程中写操作,在子进程中读操作时,我们就应该使用close函数关闭父进程中的读端和子进程的写端;这样就可以通过向管道中读写数据来实现进程之间的通讯;
总结一下,结合之前的父子通讯内容,我们多加了循环和管道,循环的目的是为了可以更容易的看到结果,管道就是用来父子通讯的,父子通讯时只能一个写一个读,而且要将时间拿捏得死死的才能通讯成功,如果只是通讯一次的话我们就需要在一个进程进行读/写操时关闭另一个的写/读端;