加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

bash – 为什么“是|睡10“管道不会失败

发布时间:2020-12-15 17:03:26 所属栏目:安全 来源:网络整理
导读:在考虑如何在我自己的一个程序中实现某个功能时,我一直想知道bash如何在内部处理以下性质的管道: yes | sleep 10 这显然什么也没做,但我不明白这不会导致错误.我原以为: 因为睡眠不从stdin读取,连接两个进程的管道将填满并导致yes在尝试写入现在的完整管道
在考虑如何在我自己的一个程序中实现某个功能时,我一直想知道bash如何在内部处理以下性质的管道:
yes | sleep 10

这显然什么也没做,但我不明白这不会导致错误.我原以为:

>因为睡眠不从stdin读取,连接两个进程的管道将填满并导致yes在尝试写入现在的完整管道时无限期阻塞
>如果使用非阻塞IO,如果首先执行yes并在睡眠过程运行之前写入管道,则会发生错误,因此没有进程连接到管道的读取端

我想这是我的一些重大误解.我已经尝试过查看bash源代码,但这已经过去了.

这是运行shell命令yes |时实际发生的情况睡10

首先,shell使用pipe system call创建一个anonymous pipe.管道系统调用打开两个文件描述符,它们是管道的读取端和写入端.无论写入写入端的内容都可以从读取端读取.

在此之后,shell使用fork system call创建两个子进程.这两个子进程并行运行.

>在一个子节点中,shell将管道的写入端连接到标准输出并关闭读取端.然后shell调用execve system call以在此过程中用代码映像替换代码映像.
程序yes只要可以就写入管道.如果管道的读取端没有活动的读取调用,则写入调用只是阻塞. (实际上有一个小缓冲区,写入将在阻塞之前填满,但这在这里无关紧要.)
>在另一个子节点中,shell将管道的读取端连接到标准输入并关闭写入端.然后shell调用execve系统调用,在此过程中用sleep代码映像替换代码映像.
程序睡眠不会持续10秒.
>原始shell进程关闭管道的两端并等待其两个子进程退出(使用wait system call).

一旦10秒钟结束,运行睡眠的过程退出.此时,管道的读取端在任何过程中都不再打开.当进程尝试写入读取端未在任何进程中打开的管道时,内核会向写入进程发送SIGPIPE信号.因此,运行yes的过程被SIGPIPE信号杀死.

此时,shell检测到管道两侧的子进程已退出. pipeline命令返回右侧的状态,即0(睡眠成功退出).

because sleep does not read from stdin,the pipe connecting both processes would fill up and cause yes to block indefinitely when it attempts to write to the now full pipe

这是对的.

if non-blocking IO is used,errors should occur if yes is executed first and writes to the pipe before the sleep process is even run and thus no process is connected to the read end of the pipe

这在一些地方是不正确的.是的,不使用非阻塞IO.它与睡眠并行执行,而不是先执行.没有任何过程连接到管道的读取端,直到睡眠退出.根据时间的不同,yes可能会在睡眠开始执行之前开始写入,甚至可能在睡眠程序的子进程被分叉之前开始写入,但是当管道调用返回时,读取结束时,读取结束时写入结束变得开放.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读