1.进程间通信在linux下是非常重要的,我们知道在linux下不同的进程的操作是互不干扰的( 独立性,这是因为每个进程都有自己的独特的虚拟地址,而这个虚拟地址就是进程与物理内存沟通的桥梁,对于不同的进程,相同的虚拟地址位置会映射到不同的物理内存上,所以进程具有独立性),那么我们难免会遇到一个进程需要另一个进程的东西,那么对于进程间通信,在这些方面就非常重要。
2.进程间通信的目的:
- 数据传输:一个进程将自己的数据传输给另一个进程。
- 资源共享:多个进程共享同一个资源。
- 通知事件:一个进程要给另一个进程去发送消息。
- 进程控制:一个进程想要去控制另一个进程,此时的控制想要拦截另一个进程的所有陷入和异常,并能够及时知道其状态的改变。
管道
1.概念:管道为进程间通信的一种方式,如同在生活中一样,管道对于我们的作用非常的大,它可以帮助我们合理,有条的去输送和排放东西。而在进程间通信中,管道分为以下两种管道:匿名管道和命名管道,并且他们具有半双工通信的功能。(两者有不同的适用情况)
2.半双工通信:一个管道有两个端口,每个端口都可以进行写入,或者读取资源,但是同一实际,相同的端口只能写入或者删除,不可同时进行。
3.管道的本质:本质为内核的一个缓冲区(内核的一块物理内存),通过多个进程访问同一个缓冲区来实现通信(由于内核对所有的进程来说都是一样的,所以在内核中开辟一块内存用于交流)。
匿名管道
1.概念:在内核中开辟这块内存,但是没有标识符,无法被其他进程找到。(所以匿名管道是针对于有亲缘关系的进程使用,例如:父子进程,由于子进程在通过父进程创建的时候,复制了父进程的文件描述信息,所以子进程也就有这个文件描述符去操作这个管道)
所以说,对于匿名管道,只有通过子进程去复制父进程的方式,才能获取同一个管道的操作句柄。
2.匿名管道的创建:
①:创建函数接口:int pipe(int pipefd[2])
其中:
- pipefd[2]:为管道的两个文件描述符,分别代表的是读取和写入。(其中,pipefd[0]表示的是从管道中读取数据,pipefd[1]表示的给管道中写入数据,成功返回0,失败返回-1)
注意:匿名管道的建立一定要在创建子进程之前,这样才能让子进程获得管道操作句柄。
②:匿名管道的操作原理:
如下图①:
为匿名管道的内核与父子进程的关系图。
而对于父子进程的操作管道缓冲去的时候如下图:
其中图中的3,4分别为读取和写入端。
如下:我们对匿名管道进行操作:
1 #include<stdio.h>
2 #include<sys/wait.h>
3 #include<unistd.h>
4 #include<stdlib.h>
5 #include<string.h>
6 int main()
7 {
8 int pipefd[2];
9 char buf[1024];
10
11 if(pipe(pipefd) == -1)//创建匿名管道
12 {
13 perror("pipe error");
14 return -1;
15 }
16 pid_t pid = fork();
17 if(pid < 0)
18 {
19 perror("fork error");
20 return -1;
21 }
22 else if(pid > 0)//父进程向管道写入数据
23 {
24 close(pipefd[0]);
25 write(pipefd[1],"i am father",12);
26 }
27 else
28 {
29 close(pipefd[1]);
30 int res = read(pipefd[0],buf,12);
31 printf("%s\n",buf);
32 printf("%d\n",res);