mkfifo打开的命名管道需要关闭吗?如果需要,应该怎么做?

17

我正在使用命名管道在一个程序(MATLAB)中捕获另一个程序(wgrib2)的输出。以下是MATLAB代码,system()函数调用命令行以创建管道:

system('mkfifo myfifo');     % Make a named pipe myfifo
% Call the external program wgrib2 and dump its output to the named pipe myfifo
system('wgrib2.exe multi_1.glo_30m.hs.201212.grb2 -ij 1 165 -ij 1 166 > myfifo &');
fid = fopen('myfifo', 'r');  % Open the named pipe
a = fscanf(fid, '%c');       % Read the output as character
fclose(fid);                 % Close the "file" (myfifo still exists afterward)

以下是我的问题:

  1. 在使用完命名管道myfifo后,我是否需要关闭它?它似乎会一直存在。
  2. 如果需要关闭myfifo,应该使用什么命令来关闭它?
  3. 我将多次运行上面的代码示例(>1000),因此如果我重复使用这个命名管道并在最后再关闭它,那么是否可以?
4个回答

11
  1. Unix将所有内容都视为文件,命名管道也不例外。如果你使用完它,可能希望关闭它,以便不会在机器上留下多余的命名管道,但你不需要关闭它。

根据下面的评论进行修改,删除并不等同于关闭。

  1. 关闭命名管道的方法与关闭任何文件相同:
    fclose(mFifo)

正如接受的答案中所提到的,关闭不会删除FIFO。您可能需要单独执行此操作。

  1. 重复使用命名管道没有问题,但是您需要知道何时完成每次迭代的读/写操作。一旦管道中的所有数据都被读取完毕,您可以自由地再次使用它,并进行多次操作。

4
这个答案是错误的。1:程序确实需要关闭管道。如果糟糕的程序不关闭文件,甚至工作站也可能用尽打开的文件。2:你不能通过删除来关闭命名管道。关闭和删除是不同的操作。 - willkil
1
你说得对。我已经更新了答案,以便后人参考。 - Jeffrey Portouw

2
您可能会将关闭与mkfifo命令的相反操作混淆。
对于MATLAB用户来说,接受的答案绝对是最好的解决方案,但我想为那些寻求命名管道的人澄清一些事情。
在类Unix系统上,命名管道(FIFO)是一种没有内容的特殊文件。 mkfifo命令会在文件系统上创建该管道(为其分配名称),但不会打开它。您需要像处理任何其他文件一样单独打开和关闭它。
  1. 使用完命名管道myfifo后,我是否需要将其关闭?运行代码后似乎仍然存在。
通常最好在不再需要它们时立即关闭/删除/释放对象。
当所有指向该管道的描述符都关闭时,管道本身(及其内容)将被销毁。您看到的只是一个名称。
  1. 如果需要关闭myfifo,应该使用哪个命令?
可以使用fclose()函数关闭命名管道。要使该管道匿名并在给定名称下不可用(可以在管道仍处于打开状态时执行此操作),您可以使用MATLAB的delete函数rm控制台命令。
  1. 我将多次运行上面的代码示例(>1000次),所以如果重复使用命名管道并在最后不关闭它是否可以?
只要每次迭代都从空管道开始(根据MATLAB文档,fscanf()函数会为您完成此操作),就可以重复使用命名管道。
可以通过两种方式重用命名管道:
  • By reusing the pipe itself (without closing it):
    system('mkfifo myfifo');
    tmp = fopen('myfifo', 'r+'); % Open the pipe in both ways (otherwise it will block)
    fid = fopen('myfifo', 'r');  % Open the pipe for reading (otherwise `fscanf` will block)
    fclose(tmp);                 % Close the auxiliary descriptor
    
    % Use the pipe multiple times...
    system('wgrib2.exe multi_1.glo_30m.hs.201212.grb2 -ij 1 165 -ij 1 166 > myfifo');
    a = fscanf(fid, '%c');
    ...
    
    % Close and delete the pipe
    fclose(fid);
    delete myfifo;
    
  • By reusing the name to open a pipe (the way you were using it).

1
根据 MATLAB的system()文档,在MATLAB中捕获系统输出时,最好不要使用命名管道。您可以直接在system()调用中捕获输出。请注意保留HTML标签。
[status, cmdout] = system('wgrib2.exe multi_1.glo_30m.hs.201212.grb2 -ij 1 165 -ij 1 166');
a = cmdout

然而,如果您坚持使用命名管道,则是的,您应该关闭它。您应该始终关闭您打开的资源。但是关闭命名管道不会删除它。


0

我不同意。你通过关闭它来关闭fifo。当系统完成时(上面的system()调用),系统会关闭fifo。当fifo关闭时,另一端就知道没有更多的数据了(EOF条件,在示例代码中没有明确的EOF检查,但在实际情况中非常可能存在),然后结束。


1
“不能同意”是指什么? - user207421
1
我来到这个网站是因为我对FIFO不太了解。但是操作员期望在关闭FIFO后删除它,而系统显然是以另一种方式工作的。就像处理任何其他文件一样,人们可以打开和关闭FIFO,或者决定将其删除。以下是一个例子: - Arseny
1
在一个终端中输入:mkfifo fifo cat - >fifo 在另一个终端中输入:cat fifo 第二个终端会接收来自第一个终端的数据,直到用户按下Ctrl-D关闭fifo。 - Arseny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接