基于管道的进程通信实验_进程间通信-管道

23bcb838f3c07bc295cc695c214cf3b0.png

pipe匿名管道

匿名管道由于没有名字, 因此只能由有亲缘关系的进程使用

#include <unistd.h>
int pipe(int fd[2]);
返回: 成功返回0, 出错返回-1

该函数返回两个文件描述符: fd[0]和fd[1], 前者打开来读, 后者打开来写.

另一个关于管道的例子, 标准I/O函数库提供了popen函数, 它创建一个管道并启动另一个进程, 该进程要么从该管道读出标准输入, 要么往该管道写入标准输出

#include <stdio.h>

FILE *popen(const char *command, const char *type);
返回: 成功返回文件指针,失败返回NULL
注意: popen不对标准错误输出做任何处理, 只有标准输出才被重定向到由它创建的管道

int pclose(FILE *stream);
返回: 成功则为shell的终止状态, 失败为-1

command是一个shell命令行, popen在调用进程和所指定的命令之间创建一个管道

- 如果type为r, 调用进程读入command的标准输出
- 如果type为w, 调用进程写到command的标准输入
  • pipe01.c演示了父子进程间通过pipe实现半双工通信
  • pipe02.c演示了使用popen创建管道

FIFO 有名管道

每个FIFO有一个路径名与之关联, 从而允许无亲缘关系的进程访问同一个FIFO。

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);
返回: 成功返回0, 失败返回-1

mkfifo函数已经隐含指定了O_CREAT | O_EXCL, 也就是说, 它要么创建一个新的FIFO, 要么返回一个EEXIST错误(如果所指定名字的FIFO已经存在)。此处可参考示例中的正确创建FIFO的步骤

- 创建出一个FIFO后, 它必须或者打开来读, 或者打开来写。不能打开来既读又写, 因为它是**半双工**的
- 如果一个FIFO, 当前尚没有进程打开它来写, 那么此时打开该FIFO来读的进程将会阻塞
- 对管道或FIFO的write总是往末尾添加数据, 对它们的read总是从开头返回数据。
- 如果对管道或FIFO执行lseek, 会返回ESPIPE错误
- 当对一个管道或FIFO的最终close发生时, 该管道或FIFO中的任何残留数据都被丢弃
  • 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值

将一个描述符设为非阻塞两种方式

  1. 调用open的时候可指定O_NONBLOCK标志
  2. 如果一个描述符已打开, 那么可以调用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

欢迎关注我的公众号: carl的修行

ade1777cd28fabf6fb373c2f534898fa.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值