0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

你所不知道的linux匿名管道知识详解

马哥Linux运维 来源:lq 2018-12-31 09:04 次阅读

相信很多在linux平台工作的童鞋, 都很熟悉管道符 '|', 通过它, 我们能够很灵活的将几种不同的命令协同起来完成一件任务。就好像下面的命令:

不过这次咱们不来说这些用法, 而是来探讨一些更加有意思的, 那就是管道两边的数据流"实时性"和管道使用的小提示。

其实我们在利用管道的时候, 可能会不经意的去想, 我前一个命令的输出, 是全部处理完再通过管道传给第二个命令, 还是一边处理一边输出呢? 可能在大家是试验中或者工作经验中, 应该是左边的命令全部处理完再一次性交给右边的命令进行处理, 不光是大家, 我在最初接触管道时, 也曾有这么一个误会, 因为我们通过现象看到的就是这样。

但其实只要有简单了解过管道这工具, 应该都不难得出解释:

管道是两边是同时进行, 也就是说, 左边的命令输出到管道, 管道的右边将马上进行处理。

管道的定义

管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条。管道的一端连接一个进程的输出。这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管道可以被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会堵塞,直到另一端的进程取出信息。当两个进程都终结的时候,管道也自动消失。

管道工作流程图

通过上面的解释可以看到, 假设 COMMAND1 | COMMAND2, 那么COMMAND1的标准输出, 将会被绑定到管道的写端, 而COMMAND2的标准输入将会绑定到管道的读端, 所以当COMMAND1一有输出, 将会马上通过管道传给COMMAND2, 我们先来做个实验验证下:

在上面的命令, 我们可以猜测下输出结果: 究竟是 睡眠6秒之后, 输出"1111222", 还是输出 "1111" 睡眠3秒, 再输出 "2222", 然后再睡眠3秒, 再输出"1111" 呢? 答案就是: 都不是! what! 这不可能, 大家可以尝试下, 我们会看到终端没反应了, 为什么呢? 这就要涉及到文件IO的缓冲方式了,这里不多说, 简单提一下文件IO的三种缓冲方式:

全缓冲:直到缓冲区被填满,才调用系统I/O函数, (一般是针对文件)

行缓冲: 遇到换行符就输出(标准输出)

无缓冲:没有缓冲区,数据会立即读入或者输出到外存文件和设备上(标准错误

因为python是默认采用带缓冲的fputs,又因为标准输出被改写到管道, 所以将会采取全缓冲的方式(shell 命令具体要看实现, 因为有些是用不带缓冲write实现,如果不带缓冲区,会直接写入管道), 所以将会采取全缓冲的方式, 也就是说, 直到缓冲区被填满, 或者手动显示调用flush刷入,才能看到输出。那我们可以将代码改写成下面两种方式吧

输出结果:

在这里我们已经能够得出结果, 如果像我们以前所想的那样, 要等到COMMAND1全部执行完才一次性输出给COMMAND2, 那么结果应该是无限堵塞。因为我的程序一直没有执行完。这样应该是不符合老前辈们设计初衷的, 因为这样可能会导致管道越来越大。然而管道也是有大小的~ 具体可以去看posix标准, 所以我们得出结论是: 只要COMMAND1的输出写入管道的写端(不管是缓冲区满还是手动flush), COMMAND2都将立刻得到数据并且马上处理。

那么管道两边的数据流"实时性"讨论到就先暂告一段落, 接下来将在这个基础上继续讨论:管道使用的小提示。

在开始讨论前, 我想先引入一个专业术语, 也是我们偶尔会遇到的, 那就是:SIGPIPE。

或者是一个更加具体的描述:broken pipe(管道破裂)

上面的专业术语都是跟管道读写规则息息相关的, 那咱们来看下 管道的读写规则吧:

1.当没有数据可读时

O_NONBLOCK (未设置):read调用阻塞,即进程暂停执行,一直等到有数据来到为止。

O_NONBLOCK ( 设置 ) :read调用返回-1,errno值为EAGAIN。

2.当管道满的时候

O_NONBLOCK (未设置): write调用阻塞,直到有进程读走数据

O_NONBLOCK ( 设置 ):调用返回-1,errno值为EAGAIN

3.如果所有管道写端对应的文件描述符被关闭,则read返回0

4.如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE

5.当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。

6.当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。

在上面我们可以看到, 如果我们收到SIGPIPE信号, 那么一般情况就是读端被关闭, 但是写端却依旧尝试写入

咱们来重现下SIGPIPE

这次执行命令需要考验手速了, 因为我们要赶在py醒过来之前, 将读端进程杀掉

输出结果

从上图我们可以验证两个点:

当我们杀掉读端时, 写端会收到SIGPIPE而默认退出, 管道结束

当我们杀掉读端时, 写端的程序并不会马上收到SIGPIPE, 相反的, 只有真正写入管道写端时才会触发这个错误

如果写入一个 读端已经关闭的管道, 将会收到一个SIGPIPE, 那读一个写端已经关闭的管道又会这样呢?

在上面也已经证明了上文提到的读写规则:如果所有管道写端对应的文件描述符被关闭,将产生EOF结束标志,read返回0, 程序退出

总结

通过上面的理论和实验, 我们知道在使用管道时, 两边命令的数据传输过程, 以及对管道读写规则有了初步的认识, 希望我们以后在工作时, 再接触管道时, 能够更加有把握的去利用这一强大的工具。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    10981

    浏览量

    206681
  • 函数
    +关注

    关注

    3

    文章

    3859

    浏览量

    61297
  • 管道
    +关注

    关注

    3

    文章

    144

    浏览量

    17802

原文标题:你所不知道的linux匿名管道知识

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Linux匿名管道和命名管道的区别

    数据。对于管道传输的数据是无格式的流且大小受限。对于管道来说,也分为匿名管道和命名管道,其中命名管道
    发表于 10-12 12:50 786次阅读

    不知道的AD功能

    不知道的AD——SmartPaste功能
    发表于 12-30 16:31

    匿名管道是什么?有何功能?

    这是我第一次出教程,若不好可在评论回复我哦(・。・)~~~~~注:匿名管道是一个未命名的单相管道,通常用来在一个父进程和一个子进程之间的传输数据。匿名
    发表于 07-09 07:26

    不知道电动车电池的型号怎么办?

    不知道电动车电池的型号怎么办?  近一年来给很多人换过电动车电池了,我发现大多数人都不知道自己的电动车电池是什么型号的,
    发表于 11-11 08:56 3208次阅读

    Miniplayer小技巧 保证有你不知道

    Miniplayer小技巧 保证有你不知道的 1,用电源充电完成后先别拔充电器,先按住开关别放再拔开线就不用更新歌曲库了。
    发表于 02-01 16:38 642次阅读

    不知道的 Vivo X9玩机小技巧!磨砂黑版你会买吗?

    Vivo x9新配色,磨砂黑版现已在火热预订中,不知道购置x9的小伙伴对手机的体验怎么样?
    发表于 03-11 10:19 2983次阅读
    你<b class='flag-5'>不知道</b>的 Vivo X9玩机小技巧!磨砂黑版你会买吗?

    低功耗蓝牙不知道怎么选型?看这里!

    低功耗蓝牙不知道怎么选型?看这里!
    发表于 07-27 16:46 12次下载

    关于你可能不知道的printf

    你可能不知道的printf
    的头像 发表于 02-05 12:28 2344次阅读
    关于你可能<b class='flag-5'>不知道</b>的printf

    不知道怎么解决精筛法兰盘腐蚀冲刷问题?

    不知道怎么解决精筛法兰盘腐蚀冲刷问题?
    发表于 06-10 15:29 4次下载

    如果你不知道斜拉链机头轮轴磨损怎么修,请看这里

    如果你不知道斜拉链机头轮轴磨损怎么修,请看这里
    发表于 06-16 14:55 1次下载

    电厂齿轮箱渗漏油不知道如何治理

    电厂齿轮箱渗漏油不知道如何治理?
    发表于 11-02 16:36 0次下载

    盘点你不知道的电缆套管知识-科兰

    电缆套管又称保护管、导管,是在电气安装中用于保护电线、电缆布线的管道,允许电线、电缆的穿入与更换。电缆套管是电力工程中推广使用的一种新型套管材料。盘点你不知道的电缆套管知识,希望能够得到帮助。 电缆
    的头像 发表于 05-25 10:24 1106次阅读

    不知道的FPC,它的发展史竟然是这样的!

    不知道的FPC,它的发展史竟然是这样的!
    的头像 发表于 11-15 10:48 438次阅读

    7种MOSFET栅极电路的常见作用,不看不知道

    7种MOSFET栅极电路的常见作用,不看不知道
    的头像 发表于 12-15 09:46 367次阅读
    7种MOSFET栅极电路的常见作用,不看<b class='flag-5'>不知道</b>!

    揭秘pcb是什么物质:你不知道的“化学战士”

    揭秘pcb是什么物质:你不知道的“化学战士”
    的头像 发表于 12-14 10:27 380次阅读