阅读封闭的命名管道块

Read on closed named pipe blocks

我正在尝试使用 Fortran 从命名管道 (FIFO) 读取数据。读取数据有效,但 Fortran 程序似乎没有注意到另一端的管道何时关闭;读取只是阻塞而不是获取 EOF。

示例程序:

program kitten
  character(256) :: buf

  open(22, file='test')
  do
     read(22, *) buf
     print*, trim(buf)
  end do
end program kitten

现在

$ mkfifo test
$ echo -e '1\n2\n3' >test &
$ ./kitten

程序按预期打印 1\n2\n3\n,但随后挂起。

相反,如果

,程序 returns EOF 错误
  1. test是普通文件;或
  2. 您将 kitten 更改为从 STDIN 读取并执行 ./kitten <test
  3. echo -e '1\n2\n3' | ./kitten;或
  4. 你用 C 写了一个等效的 kitten 程序。

我用 ifort 15.0.1gfortran 4.9.2 测试了这个,结果相同。

对于 C,我使用了 gcc

#include <stdio.h>

main() {
        char buf[256];
        FILE *test;

        test = fopen("test", "r");

        while(fgets(buf, 256, test)) {
                printf(buf);
        }
}

我对 Fortran 了解不多,但我知道您可以通过在打开中使用 read/write 模式(例如 fopen("test", "r+")

在管道上的可写文件描述符的数量下降到 0 之前,管道不会获得 EOF。当您的读取文件描述符也可写时,您永远不会获得 EOF。

所以我的猜测是 fortran 默认以 read/write 模式打开,您需要告诉它不要那样做。 This question about a fortran readonly flag 可能会有帮助。

关于 C 程序。

更好的版本是:

#include <stdio.h>
#include <stdlib.h>  // exit(), EXIT_FAILURE

int main( void ) // properly declare main()
{
    char buf[256];
    FILE * test = NULL;

    if( NULL == (test = fopen("test", "r") ) ) // check for open error
    { // then fopen failed
        perror( "fopen for test for read failed");
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    while(fgets(buf, 256, test) ) // exit loop when fgets encounters EOF
    {
        printf("%s\n",buf);
    }

    fclose( test ); // cleanup before exiting
    return 0; // properly supply a return value
}