进程间通信-管道
pipe匿名管道
匿名管道由于没有名字, 因此只能由有亲缘关系的进程使用
1 |
|
另一个关于管道的例子, 标准I/O函数库提供了popen函数, 它创建一个管道并启动另一个进程, 该进程要么从该管道读出标准输入, 要么往该管道写入标准输出
1 |
|
- pipe01.c演示了父子进程间通过pipe实现半双工通信
- pipe02.c演示了使用popen创建管道
FIFO 有名管道
每个FIFO有一个路径名与之关联, 从而允许无亲缘关系的进程访问同一个FIFO。
1 |
|
- fifo_read.c 中从文件data.txt中读取内容, 写入到FIFO中
- fifo_write.c 中从FIFO中读取内容, 写入到datafromfifo.txt中
- data.txt 是测试文件
- datafromfifo.txt 是fifo_write.c运行后生成的文件
管道和FIFO的区别
- 创建并打开一个管道, 只需要调用pipe;创建并打开一个FIFO则需在调用mkdifo后再调用open
- 管道在所有进程最终都关闭它之后自动消失。FIFO的名字则只有通过调用unlink才从文件系统中删除
- FIFO需要额外调用的好处: FIFO在文件系统中有一个名字, 该名字允许某个进程创建一个FIFO, 与它无亲缘关系的另一个进程来打开这个FIFO, 这对管道来说是不可能的(不考虑传递描述符的情况)
管道和FIFO的限制
系统加于管道和FIFO的唯一限制为:
OPEN_MAX 一个进程在任意时刻打开的最大描述符数
PIPE_BUF 可原子地写往一个管道或FIFO的最大数据量
get_sys_conf.c 获取当前系统的OPEN_MAX和PIPE_BUF值
将一个描述符设为非阻塞两种方式
- 调用open的时候可指定O_NONBLOCK标志
- 如果一个描述符已打开, 那么可以调用fcntl以启用O_NONBLOCK标志。
对于管道来说, 必须使用这种技术, 因为管道没有open调用, 在pipe中也无法指定O_NONBLOCK标志
FIFO的真正优势表现在服务器可以是一个长期运行的进程(例如守护进程), 而且与其客户可以无亲缘关系。
作为服务器的守护进程以某个众所周知的路径名创建一个FIFO, 并打开该FIFO来读。此后某个
时刻启动的客户打开该FIFO来写, 并将其命令或给守护进程的其他任何东西通过该FIFO发送出去。
使用FIFO很容易实现这种形式的单向通信(client->server)。如果守护进程需要向客户发送
回一些东西, 那就需要点技巧(例如客户需要通知守护进程要打开哪个FIFO可以给其发消息)
文中代码托管在: https://github.com/carl-wang-cn/demo/tree/master/ipc