【发布时间】:2018-07-25 21:05:09
【问题描述】:
我创建 FIFO 来在不相关的进程之间进行通信。在我的项目中,没有办法打破程序运行的无限循环。所以,我不能unlink FIFO。
我认为如果 FIFO 预先存在于写入器进程中,我可以删除并使用相同的名称重新创建。但是,如果读取进程在写入进程有机会删除并重新创建它之前打开 FIFO 怎么办?在这方面我可以使用sleep,但似乎效率不高。
此外,我还认为我可以暂停读取器进程,直到它收到来自写入器进程的信号,但读取器进程的 PID 未知。将它们视为两个独立且不同的 bash 脚本。操作系统一启动就开始执行。
- 有没有办法清理/刷新 FIFO?
open()用于打开 FIFO。如果我closeFIFO 并重新打开它以循环写入,它是否被清理/刷新? (保证?)
@编辑,
检查 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两次;该序列回显Hello和World— 并留下pause进程被杀死。相比之下,如果你省略pause,你会得到Hello,然后是错误。
标签: python ipc named-pipes mkfifo