C 使用阻塞从fifo读取数据

C 使用阻塞从fifo读取数据,c,named-pipes,C,Named Pipes,我在/tmp/foo中有一个fifo(命名管道)。 我想从fifo读取数据,如果fifo为空,程序应该休眠。 目前,这是我的解决方案: char buf [7]; FILE *f = fopen("/tmp/foo", "r"); while(!fgets(buf, 7, f)){ sleep(1); } fgets仅在某些数据写入fifo之前阻塞。但如果fifo为空,FGET不会阻塞。 是否有一种优雅的解决方案,可以在数据可用时只读,如果不可用则阻塞? 我正在使用Unix(拉斯皮安)

我在/tmp/foo中有一个fifo(命名管道)。 我想从fifo读取数据,如果fifo为空,程序应该休眠。 目前,这是我的解决方案:

char buf [7];
FILE *f = fopen("/tmp/foo", "r");
while(!fgets(buf, 7, f)){
    sleep(1);
}
fgets仅在某些数据写入fifo之前阻塞。但如果fifo为空,FGET不会阻塞。 是否有一种优雅的解决方案,可以在数据可用时只读,如果不可用则阻塞? 我正在使用Unix(拉斯皮安)

==解决方案===

我用Python解决了这个问题。 @Jonathan Leffler fopen在另一个过程打开管道之前阻塞是正确的

该问题的解决方案是在读取后关闭文件,然后重新打开。 为了防止第二个进程(如cat)保持打开状态,关闭文件并等待一小段时间就足够了。 这可以是这样的:

while True:
    f = open('/tmp/HA/temp', 'w') #blocks until pipe is opend somewhere else
    f.write("foo") #access file
    f.close() #close it
    time.sleep(0.1) #second programm might end file access

通常情况下,
fopen()
会一直阻塞,直到有一个进程(通常是另一个进程)打开了FIFO进行写入,而打开FIFO进行写入的进程会一直阻塞,直到有一个进程(通常是另一个进程)打开FIFO进行读取。一旦进程通过open,读卡器将阻塞,直到有数据要读取或所有写入器关闭FIFO。写入程序可以写入,直到FIFO达到其极限(通常为4-64千兆位-这取决于系统),或者直到FIFO打开时没有读卡器为止。[…继续…][…继续…]您描述的行为不是默认行为。有很多方法可以获得您描述的行为,但是它们涉及到修改属于文件流的文件描述符上的设置。为了让我相信你有真正的问题,你必须提供一个MCVE()。这至少是一个完整的阅读器程序,指示您如何运行编写器。读卡器应该在检查
fopen()
调用时出错;它应该打印它读取的数据;我们应该看到你作为输入提供了什么,作为输出得到了什么,以及你期望得到什么。你还应该确定你正在运行的平台。对于基于Unix的系统,我有100%的信心。我对基于Windows的系统有98%的信心。否则,我不确定。编译器和库版本可能相关,但可能不相关。这取决于您的MCVE在您的系统上可靠地再现问题,而不是在我的系统上再现问题(即macOS Sierra 10.12.3)。不过,我认为我们不需要这样做。通常,
fopen()
会一直阻塞,直到有一个进程(通常是另一个进程)打开FIFO进行写入,而打开FIFO进行写入的进程会一直阻塞,直到有一个进程(通常是另一个进程)打开FIFO进行读取。一旦进程通过open,读卡器将阻塞,直到有数据要读取或所有写入器关闭FIFO。写入程序可以写入,直到FIFO达到其极限(通常为4-64千兆位-这取决于系统),或者直到FIFO打开时没有读卡器为止。[…继续…][…继续…]您描述的行为不是默认行为。有很多方法可以获得您描述的行为,但是它们涉及到修改属于文件流的文件描述符上的设置。为了让我相信你有真正的问题,你必须提供一个MCVE()。这至少是一个完整的阅读器程序,指示您如何运行编写器。读卡器应该在检查
fopen()
调用时出错;它应该打印它读取的数据;我们应该看到你作为输入提供了什么,作为输出得到了什么,以及你期望得到什么。你还应该确定你正在运行的平台。对于基于Unix的系统,我有100%的信心。我对基于Windows的系统有98%的信心。否则,我不确定。编译器和库版本可能相关,但可能不相关。这取决于您的MCVE在您的系统上可靠地再现问题,而不是在我的系统上再现问题(即macOS Sierra 10.12.3)。不过,我认为我们不需要卷入其中。