【问题标题】:Read on closed named pipe blocks阅读封闭的命名管道块
【发布时间】:2015-11-12 11:47:54
【问题描述】:

我正在尝试使用 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,但随后只是挂起。

相反,如果

,程序会在 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);
        }
}

【问题讨论】:

    标签: c io fortran named-pipes


    【解决方案1】:

    我对 fortran 了解不多,但我知道您可以通过在 open 中使用读/写模式来重现 C 中的挂起行为(例如 fopen("test", "r+")

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

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

    【讨论】:

    • 那是正确的,添加action='read' 解决了这个问题。谢谢!
    • 连接的默认操作(读/写/读写)由编译器选择,而不是由 Fortran 指定。
    【解决方案2】:

    关于 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
    }
    

    【讨论】:

    • 注意:函数:feof() 仅在尝试读取文件末尾之后才返回 true。一般来说,它的使用几乎没有道理
    • 是的,至少可以说我的 C 已经生锈了 :-)。但这里的目的并不是创建一个“好的”C 程序,而是以一种非常简单的方式测试是 Fortran 以这种方式表现还是我的系统上有什么奇怪的东西。无论如何,感谢我在上面实现的关于 feof() 的提示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多