文章目录
- 一、进程间通信
- 1、进程间通信的目的
- 2、进程间通信发展
- 3、进程间通信分类
- 二、管道
- 1、什么是管道?
- 2、用fork来共享管道原理
- 3、站在文件描述符角度-深度理解管道
- 4、管道的五个特点
- 5、管道的四种场景
- 6、代码示例
一、进程间通信
1、进程间通信的目的
- 数据传输:一个进程需要把他的数据传给另外一个进程。
- 资源共享:多个进程之间共享同样的资源。
- 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
2、进程间通信发展
- 管道(本质上就是文件)
- System V进程间通信
- POSIX进程间通信
3、进程间通信分类
管道
- 匿名管道pipe
- 命名管道
System V IPC
- System V 消息队列
- System V 共享内存
- System V 信号量
POSIX IPC
- 消息列队
- 共享内存
- 信号量
- 互斥量
- 条件变量
- 读写锁
二、管道
1、什么是管道?
管道是Unix中最古老的进程间通信的形式。
我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”
2、用fork来共享管道原理
3、站在文件描述符角度-深度理解管道
4、管道的五个特点
- 具有血缘关系才可以进程间通信。
- 管道只能进程单向通信。
- 父子协同 同步和互斥。
- 面向字节流。
- 管道是基于文件的,而文件的声明周期是随进程的。
5、管道的四种场景
- 读写端正常,如果管道为空,写端会堵塞
- 读写端正常,如果管道已满,读端会堵塞
- 读端正常读,写端关闭,读端就会读到0,表示读到文件结尾,不会堵塞
- 写端正常读,读端关闭,则write操作会产生信号SIGPIPE,进而可能导致write进程退出。
6、代码示例
#include<iostream>
#include<sys/types.h>
#include<cstdio>
#include<unistd.h>
#include<sys/wait.h>
#include<string>
#include<cstring>
using namespace std;
#define NUM 1024
#define N 2void Writer(int fd)
{char buffer[NUM];string s="hello l am child";pid_t id=getpid();int number=0;while(1){sleep(1);buffer[0]=0;snprintf(buffer,sizeof(buffer),"%s-%d-%d",s.c_str(),id,number++);write(fd,buffer,strlen(buffer));}
}
void Reader(int id)
{char buffer[NUM];while(1){buffer[0]=0;ssize_t n=read(id,buffer,sizeof(buffer));if(n>0){buffer[n]='\0';cout<<buffer<<endl;}}
}
int main()
{int pipefd[N]={0};int n=pipe(pipefd);if(n<0) return 1;pid_t id=fork();if(id<0) return 2;if(id==0){//子进程close(pipefd[0]);Writer(pipefd[1]);exit(0);}//父进程close(pipefd[1]);Reader(pipefd[0]);pid_t rid=waitpid(id,nullptr,0);return 0;
}