第19章 进程通信
1 管道
1.1 特点
- 生产者/消费者模型
- 半双工:双向,每次都能朝一个方向传输数据
- 管道作为一组VFS对象,可以使用VFS通用结构访问(比如读写);管道被组织为pipefs这种特殊文件系统,在系统目录树没有安装点,用户看不到它们
- 管道创建后,返回一对文件描述符,分别用来读和写;然后通过fork()系统调用把这对描述符传给子进程,实现父子进程的管道通信
- 管道创建后,可以被任意进程使用,但是因为其半双工工作模式,如果有多个进程对其访问,必须加锁
- 管道创建的系统调用为pipe(),C函数库中,popen()和pclose()封装了管道相关的系统调用,更加方便
1.2 典型应用
ls | grep xxx
“|”可以创建管道;第一个子进程ls的标准输出被“|”重定向管道中;第二个子进程grep从管道读取数据作为输入,以替代标准输入,完成grep操作;grep的输出默认为标准输出。
1.3 管道数据结构
管道也是文件,可以通过VFS系统调用来访问管道,因此对于每个管道,应该有:一个索引节点对象 + 两个文件对象(读写);
如果一个索引节点表示管道,其i_pipe成员指向struct pipe_inode_info结构:
- struct wait_queue *wait:管道/FIFO 等待队列,里面是等待读写的进程
- struct pipe_buffer[] bufs:管道缓冲区描述符数组,里面包含写入管道待读出的数据
- unsigned int curbuf:待读数据所在的缓冲区索引
- unsigned nrbufs:包含待读数据的缓冲区数量,curbuf + nrbufs得到首个可写缓冲区
1.4 从管道中读数据
从一个管道中读取n个字节(阻塞读)
| 管道大小p | 有写进程 | 无写进程 |
| p = 0 | 等待数据直到拷贝n个字节,返回n | 返回0 |
| 0 < p < n | 等待数据直到拷贝n个字节,返回n | 拷贝p个字节并返回p,管道为空 |
| p >= n | 拷贝n个数据并返回n,管道还剩p-n个字节 | 拷贝n个数据并返回n,管道还剩p-n个字节 |
对于阻塞读,如果管道为空 && 没有写进程,会返回已经拷贝的字节数,不会等待;
对于非阻塞读,立刻拷贝并返回结果(拷贝的字节数),并不会关心有无写进程。
1.5 向管道中写数据
把n个字节写入管道(阻塞写)
| 可用缓冲区u | 有读进程 | 无读进程 |
| u <= n <= 4096 | 等待读,直到有n-u个字节被释放,才写入n个字节,返回n | 发送SIGPIPE并返回-EPIPE |
| u >= n | 写入n个字节,返回n | 写入n个字节,返回n |
如果管道缓冲区大小不足,且没有读进程,直接返回。
2 FIFO(命名管道)
1.2 特点
- 生产者/消费者模型
- 与管道不同的是:FIFO具有文件名且包含在系统目录树中;是一种全双工通信
- 因为存在文件名,所以可以被任意进程通过文件名访问
3 System V IPC
- Interprocess Communication,进程间通信
- IPC资源包括信号量、消息队列和共性内存,可以由任一进程访问
- 统一使用IPC数据结构,进程请求IPC资源时创建IPC数据结构
关于共享内存:
- 最高效的进程通信形式
- 允许多个进程共享内存
- 进程访问共享内存时,需要在自己的地址空间新增内存区,该内存区将与共享内存物理页框映射
- shmat()函数把一个共享内存区attach到进程上,返回内存区起始线性地址;shmat()不修改进程的页表
- 共享内存区缺省限制:最大数量4096,每个共享内存块最大32MB,所有共享内存区的最大字节数8GB —— 这些限制可以调整
- 每个IPC共享内存区属于shm特殊文件系统,在系统目录树没有安装点,因此用户不能通过VFS打开访问它的文件
4 POSIX消息队列
IPC属于内核提供给用户进程的进程间通信方法,其中包括消息队列;
POSIX消息队列属于基于POSIX标准接口的消息队列,基于消息队列实现,具有很多优点:
- 更简单的基于文件的应用接口
- 完全支持消息优先级
- 完全支持消息到达的异步通知
- 完善的超时机制
5 套接字
- server-client模型
- 适用于不同计算机通过网络交换数据
本文来自博客园,作者:moonのsun,转载请注明原文链接:https://www.cnblogs.com/moon-sun-blog/p/18842007

浙公网安备 33010602011771号