进程间通信
- 由于进程之间在执行时,是完全独立执行的,所有,进程间如果需要进行通信,就需要一块共享的区域,我们可以通过创建一个多个进程共享的区域,将所需要共享的数据放在这个共享区当中,当进程间需要通信的时候,写数据的进程将数据写入该区域,需要读数据的进程将数据从该区域中读取出来。
##进程间通信的分类
- 管道
- System V进程间通信
- POSIX IPC
##管道
- 管道是进程间通信的一种手段,通过在内核中创建一个共享区域,来实现进程间的通信,注意,所在区域是 内核,内核,内核
###管道应该如何理解呢 ?
- 管道在逻辑结构上就是一根管道,你可以理解为水管道,这根管道有两端,一个是读端,一个是写端
- 管道的设计是半双工的,也就是,一个进程在对管道进行写操作的时候,其他进程只能读取,这个写的进程占据了这个管道的写端,除非这个进程关闭这个管道的写端,否则其他进程不能对这个管道进行写入操作,读端同理,也是只能有一个进程进行读取,直到这个进程关闭读端。那么为什么不能多个进程同时对这个管道进行读取或者写入呢? 因为如果多个进程对管道进行写入的话,那管道里存储的数据顺序就会乱,因为操作系统在进行进程调度的时候,每一个进程都可能会被随时切走和切入,这样的话,如果多个进程同时拥有同一个管道的读端或写端,就会出现读写混乱.大概可以理解为,一根管道同时只能被两个进程所使用,如果有多个进程同时使用一根管道的话,就会出现读写混乱的情况。
- 在使用管道的时候,如果进程只进行写操作,那就关闭读操作。反之亦然。
- 在linux中,一切皆文件,既然如此,那管道是就是文件,那进程在打开文件的时候,就会在PCB中的file_struct记录文件的文件描述符,后面对管道的一切操作都是对文件描述符的操作。(如果你不是很懂文件描述符是什么东西,我还有一个博客是介绍文件描述符的,可以去看看)
如何开辟一个匿名管道以及使用这个匿名管道
- 在linux中,系统已经提供了管道的系统调用 ,下面的这个是匿名管道,在这个后面还有命名管道
- 匿名管道只能进行有亲缘关系的进程进行通信,常用于父子进程间的通信
- 命名管道可以进行任意进程间的通信
#include<unistd.h>
int pipe(fd[2]);
- 这里面的参数 fd[0] 是管道的读端 fd[1]是管道的写端。我们等会对管道进行操作的时候,就是通过这两个文件描述符进行操作的。返回值如果是0,就表示管道申请成功。如果失败,返回失败码
- 在下面的例子中,我用两个进程的方式,进行了一个进程间管道通信的演示,父进程读取,子进程写数据,最后,父进程将数据打印在屏幕上
- 这个代码是匿名管道的创建方法,匿名管道只能进行有亲缘关系的进程进行通信,常用于父子进程
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<error.h>
int main()
{
if(pipe(fd) != 0)
{
perror("pipe create");}
int id = fork();
if(id > 0)
{
char buf[100];
close(fd[1]);
sleep(5);
ssize_t s = read(fd[0],buf,sizeof(buf));
if(s < 0)
{
perror("read");}
buf[s] = 0;
printf("%s\n",buf);
}
else if( id ==