【问题标题】:Cleaning/flushing of named pipe命名管道的清洁/冲洗
【发布时间】:2018-07-25 21:05:09
【问题描述】:

我创建 FIFO 来在不相关的进程之间进行通信。在我的项目中,没有办法打破程序运行的无限循环。所以,我不能unlink FIFO。

我认为如果 FIFO 预先存在于写入器进程中,我可以删除并使用相同的名称重新创建。但是,如果读取进程在写入进程有机会删除并重新创建它之前打开 FIFO 怎么办?在这方面我可以使用sleep,但似乎效率不高。

此外,我还认为我可以暂停读取器进程,直到它收到来自写入器进程的信号,但读取器进程的 PID 未知。将它们视为两个独立且不同的 bash 脚本。操作系统一启动就开始执行。

  • 有没有办法清理/刷新 FIFO?
  • open() 用于打开 FIFO。如果我close FIFO 并重新打开它以循环写入,它是否被清理/刷新? (保证?)

@编辑,

检查 inode 总是产生相同的 inode 编号。我的意思是即使我通过终端使用rm <fifo.name>,然后重新创建 FIFO,也会给出相同的 inode 编号。

FIFO = '/tmp/test.fifo'
fd = os.open(FIFO, os.O_RDONLY)

info = os.fstat(fd)
print("inf fstat " + str(info.st_ino))

statinfo = os.stat(FIFO)
print("inf stat " + str(statinfo.st_ino))

输出:

inf fstat 521406
inf stat 521406

stat信息:

pi@raspberrypi:/tmp $ stat /tmp/test.fifo 
  File: /tmp/test.fifo
  Size: 0           Blocks: 0          IO Block: 4096   fifo
Device: b307h/45831d    Inode: 521406      Links: 1
Access: (0644/prw-r--r--)  Uid: ( 1000/      pi)   Gid: ( 1000/      pi)
Access: 2018-07-27 03:48:05.958234732 -0400
Modify: 2018-07-27 04:25:52.925375655 -0400
Change: 2018-07-27 04:25:52.925375655 -0400
 Birth -

comment 中所述,这是 Ubuntu 16.04 的输出的 sn-p,之前已上传到 TextUploader

soner@ubuntu:/tmp$ mkfifo test.fifo
soner@ubuntu:/tmp$ stat test.fifo 
  File: 'test.fifo'
  Size: 0           Blocks: 0          IO Block: 4096   fifo
Device: 801h/2049d  Inode: 2228362     Links: 1
Access: (0664/prw-rw-r--)  Uid: ( 1000/   soner)   Gid: ( 1000/   soner)
Access: 2018-07-26 23:41:31.482184467 +0300
Modify: 2018-07-26 23:41:31.482184467 +0300
Change: 2018-07-26 23:41:31.482184467 +0300
 Birth: -
soner@ubuntu:/tmp$ rm test.fifo 
soner@ubuntu:/tmp$ mkfifo test.fifo
soner@ubuntu:/tmp$ stat test.fifo 
  File: 'test.fifo'
  Size: 0           Blocks: 0          IO Block: 4096   fifo
Device: 801h/2049d  Inode: 2228362     Links: 1
Access: (0664/prw-rw-r--)  Uid: ( 1000/   soner)   Gid: ( 1000/   soner)
Access: 2018-07-26 23:41:46.766125062 +0300
Modify: 2018-07-26 23:41:46.766125062 +0300
Change: 2018-07-26 23:41:46.766125062 +0300
 Birth: -
soner@ubuntu:/tmp$ 

【问题讨论】:

  • 通常情况下,打开FIFO进行读取的进程在open调用中被阻塞,直到有进程打开FIFO进行写入,同样,打开FIFO进行写入的进程被阻塞,直到出现是一个打开 FIFO 进行读取的进程。一旦进程被解除阻塞,它们就可以通信,最终一个进程将关闭它们的 FIFO 文件描述符,然后通知另一个进程(读取器的 EOF、SIGPIPE 或写入器的错误)。如果任一进程希望恢复使用 FIFO,则必须重新打开它。
  • 用相同的 inode 号重新创建 FIFO 是不正常的。通常,文件系统上会有足够的其他活动,不会使用相同的 inode 重新创建 FIFO。但是,我认为重新创建的 FIFO 不太可能被内核视为相同的 FIFO,即使它们似乎具有相同的 inode。我对此不是 100% 有信心。你在哪个平台上工作?您是否对系统调用进行错误检查?
  • @JonathanLeffler 我正在使用 Raspbian OS 开发 Raspberry PI Zero W。实际上我不想关闭阅读器进程,因为它从 FIFO 读取并将一些文本信息发送到 LCD 屏幕,直到机器关闭(或所有进程都被杀死)。这是我的简化代码逻辑:textuploader.com/dznpo
  • 如果您希望读取器能够在每个写入器关闭它时不重新打开 FIFO 的情况下继续读取,您需要一个额外的写入器——可能是进程本身。一旦所有写入器都关闭了 FIFO,它就不会再接收任何数据——即使新写入器尝试打开 FIFO。如果有一个进程可以写入,读者将不会收到 EOF,但新的写入者将能够打开和写入。小心!
  • 重启时 FIFO 为空。 FIFO 保持为空,直到同时存在打开 FIFO 的读取器和写入器进程。 FIFO 在存在读取器或写入器进程时保留信息。 (考虑:{ echo Hello; echo World; pause; } > FIFO &(其中pause 是执行pause() 系统调用的程序)后跟read a < FIFO; echo $a 两次;该序列回显HelloWorld — 并留下pause 进程被杀死。相比之下,如果你省略pause,你会得到Hello,然后是错误。

标签: python ipc named-pipes mkfifo


【解决方案1】:

阅读器在从FIFO中读取之前,可以调用os.fstat(fd)os.stat(filename),检查inode号是否相同。如果不是,则意味着写入器已删除并重新创建了 FIFO,因此它应该在读取之前重新打开它。

【讨论】:

  • 你能再检查一遍问题吗?
  • 删除FIFO时,读取进程是否打开了FIFO?删除文件(任何类型的文件,包括 FIFO)后,它的 inode 可以被重用,但直到所有进程都关闭该文件后才真正删除该文件。
  • 那里看不到任何读写过程。这个答案是关于当您需要清除 FIFO 而另一个进程正在读取它时如何解决问题。您的测试不符合这些条件。
猜你喜欢
  • 2016-07-25
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多