C 使用read()函数时检查EOF
这是我第一次使用文件描述符进行读取,我已经通过反复试验进行了大约3个小时的测试,我的阅读器几乎可以正常工作了!我只需要一点帮助来检查命名管道上的EOF 好的,我打开一个(井倍数)命名管道,如下所示:C 使用read()函数时检查EOF,c,named-pipes,polling,file-descriptor,C,Named Pipes,Polling,File Descriptor,这是我第一次使用文件描述符进行读取,我已经通过反复试验进行了大约3个小时的测试,我的阅读器几乎可以正常工作了!我只需要一点帮助来检查命名管道上的EOF 好的,我打开一个(井倍数)命名管道,如下所示: fds[j].fd = open(pipeNameo, O_RDWR) ; // storing it into my file descriptor array 然后,我轮询指定的管道,以查看是否有任何内容通过(轮询在循环中): 当出现问题时,我通过将写入的文件描述符发送到此函数来处理文件: i
fds[j].fd = open(pipeNameo, O_RDWR) ; // storing it into my file descriptor array
然后,我轮询指定的管道,以查看是否有任何内容通过(轮询在循环中):
当出现问题时,我通过将写入的文件描述符发送到此函数来处理文件:
int processFileDes( int fd )
{
char buf[10] ;
read(fd, buf, 1) ;
char curr = buf[0] ;
while (curr != EOF)
{
if ( curr == ' ')
{
// do nothing it is a space
}
else if ( curr == '\n')
{
printf("NEW LINE!\n") ;
}
else
{
int num = curr - '0' ; // turns char number into an int
printf("Curr Num: %d\n", num) ;
}
printf("BEFORE\n"); // Gets stuck here when EOF, this is the string of output
read(fd, buf, 1) ;
printf("AFTER\n") ;
curr = buf[0] ;
}
printf("Success!\n") ; // this is never printed
return 0 ;
}
除了在读取完所有字符后,read()
函数被卡住(我想是在等待返回)之外,所有操作都非常正常。EOF应该在哪里。我需要能够检查EOF
我尝试了一种解决方法,通过计算读取的字符数(因为我知道输入的大小)来停止程序的读取,它会起作用,唯一的问题是当最后一个字符后有一个空格时,它会导致循环轮询返回1,并在剩余的空格上再次运行processFile()
(非有效输入)留待读取
请帮忙:')
输入只是一个数字矩阵,如下所示:
0 1 1
2 0 3
1 0 0
read返回值为0表示EOF。您需要打开非阻塞,因为管道将等待数据可用:
fds[j].fd = open(pipeNameo, O_RDWR | O_NONBLOCK);
首先,您应该确保您实际碰到了管道上的文件末尾 当您打开FIFO(命名管道的另一个名称)进行读取时,进程将等待另一个进程打开它进行写入并写入内容。然后,它将继续等待更多的输入,直到所有打开它进行写入的进程都将其关闭 您可以使用和在两个终端窗口中测试这一点: 在另一个终端:
$ cat > test-fifo # This is the writing process; type here and see it above
现在,如果关闭写入过程,读取过程将退出,因为它已到达文件的末尾
但是,如果您打开两个写入进程,并且只退出一个进程,FIFO将保持打开状态,而读取端将不会结束,直到您关闭这两个进程
因此,一种很容易犯错误的可能性是,仍然在某个地方打开FIFO进行写入,因此读取端永远不会得到文件结束状态。需要注意的一件事是,如果这个过程本身也有FIFO打开以供写入,或者如果产生数据的任何过程只是保持管道打开,而不是在完成后关闭管道
如果无法确定某个进程是否已打开管道进行写入,请尝试或确定可能已打开管道的任何进程
关于您的代码的一些其他注释,也可能是问题:
char buf[10] ;
read(fd, buf, 1) ;
char curr = buf[0] ;
while (curr != EOF)
这不是确定是否使用低级、无缓冲原语到达文件末尾的方式;这就是使用缓冲stdio操作的方法,比如。使用read
,您使用所需的读取长度调用它,它返回它可以读取的长度(可能小于您要求的长度)、0(如果它位于文件末尾)和-1(错误时)。如果未检查读取的返回值
,则存在错误。请注意,并非所有错误都是致命的
即使您使用的是fgetc
,此代码也是有缺陷的fgetc
返回一个int,而不是char,因此它可以返回整个字符值范围以及EOF的哨兵值
printf("BEFORE\n"); // Gets stuck here when EOF, this is the string of output
read(fd, buf, 1) ;
printf("AFTER\n") ;
在轮询调用之间,通常不应尝试读取同一文件描述符两次;否则,如果文件描述符上没有更多可用数据,则第二个文件可能会阻塞。相反,您应该对一定数量的数据进行一次读取,但要准备好read
,以返回比您请求的数据更少的数据,并返回轮询循环,找出现在可用的数据(可能在不同的fd上,如果此fd没有可用的新数据,但另一fd有可用的数据)
使用
read
的方法通常是一次读取整个缓冲区,而不是一次读取一个字符。问题是,一旦达到EOF,它就不会返回。read()在循环的最后一次迭代中被卡住。我的循环结束时的printf(“AFTER\n”)
从未打印最后一次,这意味着read()在尝试执行读取并且已经是EOF时永远不会完成。@DavidBaez您的代码从不检查read的返回值。此外,由于您正在从管道读取数据,因此在管道的另一端关闭之前,您不会看到EOF。发生了吗?@DavidBaez如果read()返回0,就不应该再次调用read()。代码需要检查read()的返回值,并处理0(EOF)和-1(错误)的返回值。您还需要确保命名管道的另一端实际上已关闭。在另一端关闭之前不会有EOF。我以前从未听说过fuser和lsof。此外,IMHO这是一个完美的总结,并提示了pipe/fifo的缺陷+谢谢。
char buf[10] ;
read(fd, buf, 1) ;
char curr = buf[0] ;
while (curr != EOF)
printf("BEFORE\n"); // Gets stuck here when EOF, this is the string of output
read(fd, buf, 1) ;
printf("AFTER\n") ;