如何在命名管道中的 EOF 之后恢复读取

Posted

技术标签:

【中文标题】如何在命名管道中的 EOF 之后恢复读取【英文标题】:How to resume reading after EOF in named pipe 【发布时间】:2017-03-26 08:44:26 【问题描述】:

我正在编写一个程序,它打开一个命名管道进行读取,然后处理写入该管道的所有行:

err = syscall.Mkfifo("/tmp/myfifo", 0666)
if err != nil 
    panic(err)


pipe, err := os.OpenFile("/tmp/myfifo", os.O_RDONLY, os.ModeNamedPipe)
if err != nil 
    panic(err)


reader := bufio.NewReader(pipe)
scanner := bufio.NewScanner(reader)

for scanner.Scan() 
    line := scanner.Text()
    process(line)

只要写入过程不重新启动或由于其他原因发送 EOF,此方法就可以正常工作。发生这种情况时,循环终止(正如 Scanner 的规范所预期的那样)。

但是,我想保持管道打开以接受进一步的写入。我可以当然只是重新初始化扫描仪,但我相信这会产生一个竞争条件,即扫描仪可能尚未准备好,而新进程已开始写入管道。

还有其他选择吗?我需要直接使用File 类型吗?

【问题讨论】:

你需要一台新的扫描仪,哪里会有比赛? @JimB 我担心的是作者断开连接,我得到一个 EOF 并退出循环以重新创建扫描仪。在此完成之前,写入器已重新启动并继续写入管道。可能这只会导致写入被缓冲?我想这取决于我是否还需要关闭文件句柄。 【参考方案1】:

来自bufio GoDoc:

Scan ... 在扫描停止时返回 false,无论是到达输入末尾还是错误。

因此您可以让文件保持打开并读取直到 EOF,然后在文件更改或定期(即创建一个 goroutine)时再次触发 scanner.Scan(),并确保 pipe 变量不超出范围,以便您可以再次引用它。

如果我正确理解您对竞态条件的担忧,这将不是问题(除非必须同步写入和读取操作),但是当重新初始化扫描仪时,它最终会回到文件的开头.

【讨论】:

同样来自文档:Scanning stops unrecoverably at EOF -- 你不能再调用 Scan 了。

以上是关于如何在命名管道中的 EOF 之后恢复读取的主要内容,如果未能解决你的问题,请参考以下文章

如何阻止在 Ruby 中读取命名管道?

如何避免命名管道中的多个作者?

shell 命名管道,进程间通信, ncat作http server

c中的命名管道

Bash 重定向:命名管道和 EOF

如何写入命名管道而不等待读取管道