【问题标题】:Should named pipes opened with mkfifo be closed and how?是否应该关闭使用 mkfifo 打开的命名管道以及如何关闭?
【发布时间】:2013-01-16 22:09:35
【问题描述】:

我正在使用命名管道在另一个程序 (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),所以如果我重用命名管道并且直到结束才关闭它可以吗?

【问题讨论】:

    标签: matlab shell command pipe named-pipes


    【解决方案1】:

    您可能会将关闭与mkfifo 命令的反义词混淆。

    对于 MATLAB 用户来说,公认的答案绝对是最好的解决方案,但我想为那些来到这里命名管道的人澄清一下。


    在类 Unix 中,命名管道 (FIFO) 是一种特殊类型的文件,没有内容。 mkfifo 命令在文件系统上创建管道(为其分配名称),但不打开它。您需要像任何其他文件一样单独打开和关闭它。

    1. 使用命名管道myfifo后是否必须关闭它?代码运行后似乎仍然存在。

    一旦不再需要它们,最好立即关闭/删除/释放它们。
    当所有描述符都关闭时,管道本身(及其内容)会被破坏。你看到的只是一个名字。

    1. 如果myfifo需要关闭,关闭的命令是什么?

    命名管道可以用fclose() function 关闭。要使管道在给定名称下匿名且不可用(可以在管道仍然打开时完成),您可以使用 MATLAB 的 delete functionrm 控制台命令。

    1. 我会多次运行上面的代码示例(>1000),所以如果我重用命名管道并且直到结束才关闭它可以吗?

    只要每次迭代都从一个空管道开始,就可以重用命名管道(根据 MA​​TLAB 文档,fscanf() function 将为您执行此操作)。

    命名管道可以通过两种方式重用:

    • 通过重用管道本身(不关闭它):
      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;
      
    • 通过重用名称来打开管道(您使用它的方式)。

    【讨论】:

      【解决方案2】:
      1. 没有。 Unix 将所有内容都视为文件。命名管道没有什么不同。如果你用完了它,你可能想关闭它,以免你的机器被命名管道弄得一团糟,但你不需要关闭它。

      已编辑以反映以下评论,这是正确的。删除 != 关闭。

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

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

      1. 重用命名管道没有任何问题。但是,由您自己决定何时完成每次迭代的读/写操作。从管道中读取所有数据后,您可以随意再次使用它,次数不限。

      【讨论】:

      • 这个答案是错误的。 1:程序确实需要关闭管道。如果坏程序不关闭它们的文件,甚至工作站也可能用完打开的文件。 2:您不要通过删除命名管道来关闭它。关闭和删除是不同的操作。
      • 你是对的。我已经更新了后代的答案。
      【解决方案3】:

      您可能不应该在 MATLAB 中使用命名管道来捕获系统输出。根据MATLAB's system() documentation,您可以直接在system() 调用中捕获输出:

      [status, cmdout] = system('wgrib2.exe multi_1.glo_30m.hs.201212.grb2 -ij 1 165 -ij 1 166');
      a = cmdout
      

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

      【讨论】:

        【解决方案4】:

        不能同意。您通过关闭它来关闭fifo。系统完成后关闭 fifo(上面的 system() 调用)。当fifo关闭时,另一方知道没有更多数据(EOF条件,示例代码中没有明确的EOF检查,但在真实代码中很可能)并完成。

        【讨论】:

        • '不能同意'什么?
        • 我其实是来这个网站的,因为对fifos不太了解。但是 op 期望在关闭 fifo 后删除它,而系统显然以其他方式工作。就像任何其他文件一样,可以打开和关闭 fifo 或决定删除它。示例如下:
        • 在一个终端中:mkfifo fifo cat - >fifo 在另一个终端中:cat fifo 第二个终端从第一个终端接收数据,直到用户按下 Ctrl-D 关闭 fifo。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-16
        • 1970-01-01
        • 2012-11-28
        相关资源
        最近更新 更多