发送 EOF 到命名管道 - 清理/干燥 fifo

发送 EOF 到命名管道 - 清理/干燥 fifo

如果我有一些随机进程从命名管道读取:

tail -f MYNAMEDPIPED 
cat MYNAMEDPIPE | someOtherProc

在其他地方,我可以通过名称来处理 MYNAMEDPIPED。有没有一种安全干净的方法可以通过删除 MYNAMEDPIPED 或以某种方式“干燥它”来停止尾部进程?

换句话说

MYNAMEDPIPED.noMoreDataIsComingThroughSoPleaseStopTailingThis()

:)

从其中一条评论来看,它说将 EOF 发送到 MYNAMEDPIPE。但我不知道该怎么做。

这表明我面临的困难:

http://comp.os.linux.questions.narkive.com/2AW9g5yn/sending-an-eof-to-a-named-pipe

答案1

EOF不是一个字符也不是一个“事件”,不能通过管道发送,或“馈送到”其写入端,正如一些顽固的都市传说所暗示的那样。

仅有的EOF在管道/fifo 的读取端生成 an(即使read(2)其返回 0)的方法是关闭其写入端的所有打开句柄。

如果所有以写入模式打开命名管道的进程以及所有继承文件描述符的子进程fork()都被终止,这将自动发生[1]。

read(2)如果管道以读/写模式打开,则命名管道上的a 不可能返回 0,例如。和

exec 7<>/path/to/fifo

因为在这种情况下,管道的两端都有一个文件描述符/句柄,并且关闭写入端也会关闭读取端,从而使 a 不可能read(2)返回 0(管道不支持任何类型的半关闭,而套接字则不支持)和shutdown(2))。

SCM_RIGHTS[1] 以及通过unix 套接字上的辅助消息接收到文件描述符的所有进程。


请注意tail -f 根据定义不会终止于EOF,无论它读取的文件是常规文件还是特殊文件。终止持有文件描述符的打开句柄的所有进程的一种方法是fuser(1)

tail -f /path/to/fifo
...
> /path/to/fifo  # let any blocking open(2) through
fuser -TERM -k /path/to/fifo

请注意,这也会杀死(无意中)从/path/to/fifo其父级继承开放句柄的进程。

答案2

您不能“发送 EOF”。根本没有“EOF 字符”会通过管道。

通常,Linux 程序在阻塞模式下使用 (2) 从文件描述符读取数据read,用接收到的数据填充缓冲区,并返回读取的字符数。当read返回 0 时,即已读取 0 个字节,大多数程序将其解释为文件结束。

fsync程序可以使用(2)在缓冲区满之前刷新管道的一侧。在这种情况下,即使缓冲区为空,读取器read也会立即返回,并返回 0 作为读取字节数。

您可以通过运行 来观察这一点cat,输入一些字符(不返回)并按下 Ctrl-D(这会导致终端刷新)。此时,cat将打印输入的字符。再次按下 Ctrl-D,并且cat'sread将返回 0 个字节,假设cat已到达文件末尾。由于使用了行缓冲,cat当您按下 Return 时也会打印其输入。

相关内容