IO进程 day06
IO进程 day06
- 10. 线程间的通信机制
- 10.5. 死锁
- 死锁产生的必要条件
- 11. 进程间通信机制
- 11.1. 进程间的通信方式
- 11.2.无名管道
- 特点
- pipe
- 11.3. 有名管道
- 特点
- mkfifo
10. 线程间的通信机制
10.5. 死锁
是指两个或两个以上的进程/线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去
死锁产生的必要条件
- 互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
- 不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
- 请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
- 循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
注意当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。
11. 进程间通信机制
11.1. 进程间的通信方式
- 传统的通信方式:无名管道,有名管道,信号
- system V IPC对象:共享内存,消息队列,信号灯集
- BSD:套接字
11.2.无名管道
特点
- 只能用于具有亲缘关系的进程之间的通信
- 半双工的通信模式
- 管道可以看成是一种特殊的文件,对于它的读写可以使用文件IO如read、write函数.
- 管道是基于文件描述符的通信方式。当一个管道建立时,它会创建两个文件描述fd[0]和fd[1]。其中fd[0]固定用于读管道,fd[1]固定用于写管道。
pipe
#include <unistd.h>
int pipe(int pipefd[2]);
功能:创建无名管道
参数:int pipefd[2]
创建的文件描述符,下标为0,1对应两个文件描述符
返回值:成功返回0,失败返回EOF
注意
- 管道中读取空了之后,没有数据时,读取阻塞
char buf[32] = ""; // 写入和读取的地址
// 管道中没有数据时,读取阻塞
read(pipefd[0], buf, 5);
printf("buf = %s\n", buf);
- 管道中写满了数据,写入阻塞,写满:64k,至少读出4k空间才能进行写操作
char full[65536] = ""; // 写满(64k = 65536)
char arr[4096] = ""; // 空出4k空间
// 管道中写满数据时,写入阻塞
write(pipefd[1], full, 65536);
// 读出4k空间
read (pipefd[0], arr, 4096);
printf("write befor\n");
write(pipefd[1], "a", 1);
printf("write after\n");
- 关闭读端,写操作会导致管道破裂,进程结束,收到SIGPIPE
// 关闭读端,写操作会导致管道破裂,进程结束,收到SIGPIPE
close(pipefd[0]);
write(pipefd[1], "a", 1);
printf("write after\n");
11.3. 有名管道
特点
- 有名管道可以使互不相关的两个进程互相通信
- 有名管道可以通过路径名来指出,并且在文件系统中可见,但内容存放在内存中
- 通过文件IO来操作
- 先进先出
- 写满和读空时阻塞
- 不支持lseek操作
mkfifo
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
功能:创建有名管道
参数:
const char *pathname
管道文件名
mode_t mode
文件权限,8进制数表示0777
返回值:成功返回0,失败返回EOF,更新error
注意
- 在打开管道时,只有完成读端和写端都打开的操作后,才会完成打开管道文件的操作,否则会在打开管道文件的位置阻塞