读取已关闭的命名管道块
我试图从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错误if
-
test
是一个常规文件; 要么 - 你改变
kitten
从STDIN读取并做./kitten <test
或 -
echo -e '1\n2\n3' | ./kitten
echo -e '1\n2\n3' | ./kitten
; 要么 - 你在C写一个相当的
kitten
程序
我使用ifort 15.0.1
和gfortran 4.9.2
进行了测试,结果相同。
对于CI使用gcc
和
#include main() { char buf[256]; FILE *test; test = fopen("test", "r"); while(fgets(buf, 256, test)) { printf(buf); } }
我不太了解fortran,但我知道你可以通过在你的打开中使用读/写模式重现C中的悬挂行为(例如fopen("test", "r+")
管道在其上的可写文件描述符数量下降到0之前不会获得EOF。当您的读取文件描述符也可写时,您永远不会获得EOF。
所以我的猜测是fortran在默认情况下以读/写模式打开,你需要告诉它不要这样做。 关于fortran readonly旗帜的这个问题可能有所帮助。
关于C程序。
一个更好的版本是:
#include #include // 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 }