进程间通信
进程间通信的目的:
- 数据传输:一个进程需要将它的数据发送给另一个进程
- 资源共享:多个进程之间共享同样的资源。
- 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
- 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变
进程间通信方式:
管道:匿名管道、命名管道
System V IPC:
- System V 消息队列
- System V 共享内存
- System V 信号量
POSIX IPC:
- 消息队列
- 共享内存
- 信号量
- 互斥量
- 条件变量
- 读写锁
1.管道:半双工通信(可选方向的单向传输)
本质:内核中的一块缓冲区
生命周期随进程
进程间通信原理:让多个进程通过访问相同的缓冲区来实现通信
匿名管道:只能用于有亲缘关系的进程间通信
一个进程创建匿名管道,操作系统在内核中重建一块缓冲区,并返回两个文件描述符作为管道的操作句柄,一个用于读,一个用于写
操作接口:
int pipe(int pipefd[2]);
pipefd:至少具有两个整形元素的数组
创建一个管道,通过pipefd获取系统返回的管道操作句柄,其中pipefd[0]用于从管道读取数据,pipefd[1]用于向管道写入数据
返回值:成功返回0,失败返回-1
管道读写特性:
若管道中没有数据,则read会阻塞,直到数据被写入
若管道中数据满了,则write会阻塞,直到数据被读取
若管道的所有读端被关闭,则write会触发异常,进程退出
若管道所有写端被关闭,则read会返回0(所有写端被关闭)
命名管道:在内核中这块缓冲区是有标识的,所有的进程都可以通过标识来找到这块缓冲区
命名管道文件的打开特性:
若文件当前没有已经被以读的方式打开,则以O_WRONLY打开时会阻塞
若文件当前没有已经被以写的方式打开,则以O_RDONLY代开时会阻塞
命名管道的读写特性:同匿名管道
管道:
分类:匿名管道,命名管道
特性:半双工通信
管道的读写特性,命名管道打开特性
管道的生命周期随进程
管道自带同步与互斥(管道读写数据大小不超过PIPE_BUF时是安全的)
管道提供字节流服务(传输灵活,但是会出现粘包问题---数据没有明显间隔)
2、共享内存
最快的进程间通信方式(数据传递不涉及内核),主要用于进程间的数据共享
原理:申请一块物理内存,将这块物理内存通过页表映射到进程的虚拟地址空间中,接下来进程
通过虚拟地址访问这块物理内存,多个进程映射同一块物理内存可以通过这块内存实现数据共享
流程:
- 创建共享内存 shmget()
- 将共享内存映射到虚拟地址空间 shmat()
- 直接通过虚拟地址进行内存操作
- 解除映射关系 shmdt()
- 删除共享内存 shmctl()
删除流程:共享内存在删除时,首先会判断当前映射链接数是否为0,若为0则直接删除,否则表示还有进程在使用,则不能被立即删除,并且会拒绝其他进程的链接
特性:进程间通信最快的方式—直接通过虚拟地址操作数据,相较于其他两种方式少了用户态和内核态之间的数据拷贝操作
3、消息队列:用于多个进程间有类型的数据块传输
原理:内核中的一个优先级队列
生命周期:生命周期随内核
ipcs:查看IPC
-m 查看共享内存
-s 查看信号量
-q 查看消息队列
ipcrm 删除IPC
4、信号量:用于实现进程间的同步与互斥操作
同步:保证多个进程之间对临界资源访问的时序合理性
互斥:进程之间同一时间对临界资源访问的唯一性
本质:内核中的一个计数器(资源计数,统计有多少资源,判断能否进行操作)+等待队列
原理:
进程对临界资源访问前先进行资源技术判断
- 若计数大于0表示可以操作;则计数减一;判断操作直接返回
- 若计数小于等于0;表示不可操作;将进程PCB状态修改为阻塞状态;将PCB加入到等到队列中其他进程创建一个资源;计数加一;唤醒等待队列上的所有进程