Linux IPC之管道和FIFO

导言:管道是UNIX系统上最古老的IPC方法,管道提供了一种优雅的解决方案:给定两个运行不同程序的进程,在shell中如何让一个进程的输出作为另一个进程的输入?管道可以用来在相关(一个共同的祖先进程创建管道)进程之间传递数据。FIFO是管道概念的一个变体,它们之间的一个重要差别在于FIFO可以用于任意进程间的通信。

概述

每个shell用户都对在命令中使用管道比较熟悉,例如,统计一个目录中文件的数目:

ls | wc -l

解释:为了执行上面的命令,shell创建了两个进程来分别执行ls和wc(通过使用fork()和exec()来完成)。如下图所示:

pic

管道的特征

  1. 一个管道是一个字节流(无边界,顺序的)
    意味着在使用管道时,是不存在消息或消息边界的概念,从管道中读取数据的进程可以读取任意大小的数据块,而不管写入进程写入管道的数据块的大小是什么。此外,通过管道传递的数据是顺序的,从管道中读取出来的字节顺序与它们被写入管道的顺序是完全一样的,在管道中无法使用lseek()来随机地访问数据。

    如果需要在管道中实现离散消息的传递,就必须要在应用程序中完成这些工作,但是对于此类需求,最好使用其他IPC机制,比如,消息队列,数据报socket。

  2. 从管道中读取数据(读空管道将阻塞,读端遇0为关闭)
    试图从一个当前为空的管道中读取数据将会被阻塞直到至少有一个字节被写入到管道中为止。如果管道的写入端被关闭了,那么从管道中读取数据的进程在读完管道中剩余的所有数据之后将会看到文件结束(即,read()返回0)。

  3. 管道是单向的
    在管道中数据的传递方向是单向的,管道的一端用于写入,另一端用于读取。

  4. 可以确保写入不超过PIPE_BUF字节的操作是原子的
    如果多个进程写入同一个管道,那么如果每个进程在一个时刻写入的数据量不超过PIPE_BUF字节,那么就可以确保写入的数据不会发生相互交叉的情况。SUSv3要求PIPE_BUF至少为_POSIX_PIPE_BUF(512),不同的UNIX实现上的PIPE_BUF不同,在Linux上,PIPE_BUF的值为4096

  5. 管道的容量是有限的
    管道其实是一个在内核中维护的缓冲器,这个缓冲器的存储能力是有限的。一旦管道被填满后,后续向管道的写入操作就会被阻塞,直到读者从管道中移除了一些数据为止。

SUSv3并没有规定管道的存储能力,从Linux2.6.11起,管道的存储能力是65536字节(64KB),其他UNIX实现上的管道的存储能力可能是不同的。一般来讲,一个应用程序无需知道管道的实际存储能力,如果需要防止写者进程阻塞,那么管道中读取数据的进程应该被设计成以尽可能快的速度从管道中读取数据。

在内核中针对管道使用较大的缓冲器的原因是:效率。每当写者充满管道时,内核必须要执行一个上下文切换以允许读者被调度来消耗管道中的一些数据。使用较大的缓冲器意味着需要执行的上下文切换次数更少。
从Linux2.6.35开始就可以修改一个管道的存储能力了。Linux特有的fcntl(fd, F_SETPIPE_SZ, size)调用会将fd引用的管道的存储能力修改为至少size字节。非特权进程可以将管道的存储能力修改为范围在系统的页面大小到/proc/sys/fs/pipe-max-size中规定的值之内的任何一个值。pipe-max-size的默认值是1048576字节(1MB)。fcntl(fd, F_GETPIPE_SZ)调用返回为管道分配的实际大小。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值