如果一系列命令在Linux中通过管道传输,它会高效地处理它,即如果最后一个子进程已经终止,它会终止前一个子进程。例如,
cat filename | head -n 1
zcat filename | head -n 1
hadoop fs -cat /some/path | head -n 1
在上述每个命令中,cat命令将花费相当长的时间,但组合命令执行速度很快。如何在内部完成?cat
终止后,OS是否立即为第一个命令(cat
命令)提供SIGTERM、SIGKILL?
我想在Python中做一些类似的事情,并想知道什么是最好的方法。我尝试做以下事情:
p1 = Popen(['hadoop','fs','-cat',path], stdout=PIPE)
p2 = Popen(['head','-n',str(num_lines)], stdin=p1.stdout,stdout=PIPE)
p2.communicate()
p1.kill() or p1.terminate()
这样做有效率吗?
1条答案
按热度按时间m528fe3b1#
实际上,我认为进程在head关闭时发送
SIGPIPE
。信号管
SIGPIPE信号在进程试图写入没有进程连接到另一端的管道时发送给进程。
另外,从a question on SIGPIPE的一些回答中可以看出:
...
您可以看到,当带有挂起的写入操作的文件描述符关闭时,SIGPIPE随即发生。虽然写入操作最终将返回-1,但信号的全部意义在于异步通知您写入操作不再可能。这是使整个优雅的管道协同例程结构在UNIX中工作的部分原因。
...
https://stackoverflow.com/a/8369516/2334407
...
https://www.gnu.org/software/libc/manual/html_mono/libc.html
这个链接说:
一个管道或FIFO的两端必须同时打开。如果你从一个没有任何进程写入的管道或FIFO文件中读取(可能是因为它们都关闭了文件,或者退出了),读取返回文件结束。写入一个没有阅读进程的管道或FIFO被视为错误状态;它生成SIGPIPE信号,如果该信号被处理或阻塞,则会失败并显示错误代码EPIPE。
...
https://stackoverflow.com/a/18971899/2334407
我认为这是为了获得正确的错误处理,而不需要在所有内容中写入大量代码到管道。
有些程序忽略write()的返回值;如果没有SIGPIPE,它们将无用地生成所有输出。
检查write()返回值的程序在失败时可能会打印错误消息;这对于破裂的管道是不适当的,因为它实际上不是整个管线的错误。
https://stackoverflow.com/a/8370870/2334407
现在,为了回答你的问题,最好的方法是什么,我会说不要发送任何信号。相反,读取你需要的数据,然后简单地关闭管道。操作系统内核会在你之后自动清理,并发送
SIGPIPE
到必要的进程。