进程间通信(IPC):操作系统为用户提供的几种进程间通信方式。
管道–用于进程间的数据传输
本质:内核中的一块缓冲区–通过半双工(可以选择方向的单向通信)通信实现数据传输。
原理:通过让多个进程都能访问到同一块缓冲区,来实现进程间通信。
管道分类:匿名管道\命名管道
匿名管道
概念:这块内核中的缓冲区没有标识。
特性:只能用于具有亲缘关系的进程间通信。子进程通过复制父进程的方式,获取到管道的操作句柄进而实现访问一个管道通信。
创建管道时,操作系统会提供两个操作句柄(文件描述符),其中一个用于从管道读取数据,一个向管道写入数据。每次通信时只能有一个操作。
文件描述符:内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。相当于就是内核给这个文件的一个标记。
int pipe(int pipefd[2]);创建一个匿名管道,向用户通过参数pipefd返回管道的操作句柄。
pipefd[0]:用于从管道读取数据
pipefd[1]:用于从管道写入数据
返回值:0-成功,-1-失败
特性:若管道中没有数,则read会阻塞;若管道写满了,则write会阻塞;管道自带同步与互斥。
同步:对临界资源访问的合理性。一个进程使用完资源之后,若是还要再次使用,若有其他进程等待使用资源,该进程就必须排队等待。
互斥:通过保证同一时间只有一个进程能够访问临界资源,保证临界资源访问的安全性。对管道进行数据操作的大小不超过PIPE_BUF=4096的时候,则保证操作的原子性。
若管道所有的写端被关闭(表示当前没有进程继续写入数据了),read读完管道中的数据之后,就不会再阻塞而是返回0。
若管道所有读端被关闭(表示没有进程读取数据了),继续write会触发异常,程序退出。
管道的使用:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<string.h>
5 int main(){
6
7 int pipefd[2]={
0};
8 int ret=pipe(pipefd);
9 if(ret<0){
10 perror("pipe error");
11 return -1;
12 }
13 pid_t pid=fork();
14 if(pid<0){
15 perror("fork error");
16 return -1;
17 }else if(pid==0){
18 char buf[1024]={
0};
19 int ret=read(pipefd[0],buf,