Dav*_*aez 1 c file-descriptor named-pipes polling
这是我第一次使用文件描述符进行读取,并且我已经通过反复试验进行了大约3个小时的测试,而我的读取器几乎可以正常工作!我只需要一点帮助来检查命名管道上的EOF。
好的,这样我就可以打开一个(多个)命名管道:
fds[j].fd = open(pipeNameo, O_RDWR) ; // storing it into my file descriptor array
Run Code Online (Sandbox Code Playgroud)
然后我在轮询命名管道以查看是否发生了任何事情(轮询在循环内):
int ret = poll(fds, numOfPipesUsed, timeout_msecs);
Run Code Online (Sandbox Code Playgroud)
当确实发生问题时,我通过发送写入该函数的文件描述符来处理文件:
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 ;
}
Run Code Online (Sandbox Code Playgroud)
一切工作都很好,除了一旦所有字符都已被读取,read()函数就会卡住(我想等待返回)。EOF应该在哪里。我需要能够检查EOF。
我尝试了一种变通方法,该方法通过计算读取的字符数来停止程序读取(因为我知道输入的大小),并且它可以正常工作,唯一的问题是最后一个字符后有空格会导致循环轮询以返回1,并processFile()在剩下要读取的其余空间(无效输入)上重新运行。
请帮忙 :')
输入只是一个数字矩阵,如下所示:
0 1 1
2 0 3
1 0 0
Run Code Online (Sandbox Code Playgroud)
您首先应该确保您实际上在管道上碰到文件结尾。
当您打开FIFO(命名管道的另一个名称)进行读取时,该进程将等待,直到另一个进程打开它进行写入并写入内容。然后它将继续等待更多输入,直到所有可打开以供写入的进程将其关闭为止。
$ mkfifo test-fifo
$ cat test-fifo # This is the reading process and will wait for data to read
Run Code Online (Sandbox Code Playgroud)
在另一个终端:
$ cat > test-fifo # This is the writing process; type here and see it above
Run Code Online (Sandbox Code Playgroud)
现在,如果您关闭写入过程,则读取过程将退出,因为它已到达文件末尾。
但是,如果您打开两个写入过程,并且仅退出一个,则FIFO将保持打开状态,并且读取端将不会结束,直到您将它们都关闭为止。
因此,很容易犯一个错误,一种可能是仍然使FIFO在某个地方打开以进行写入,因此读取结束将永远不会结束文件状态。值得一提的是,如果该进程本身也打开了FIFO以进行写入,或者无论产生了什么进程,则数据只是保持管道处于打开状态,而不是在完成后关闭管道。
如果您无法确定某个进程是否已打开要写入的管道,请尝试fuser或lsof确定可能打开该管道的任何进程。
关于您的代码的其他一些注释,也可能是问题:
char buf[10] ;
read(fd, buf, 1) ;
char curr = buf[0] ;
while (curr != EOF)
Run Code Online (Sandbox Code Playgroud)
这不是确定是否使用低级,无缓冲的read原语命中文件末尾的方式。这就是使用缓冲的stdio操作(例如)执行的操作fgetc。使用read,您可以调用它并具有所需的读取长度,然后返回可以读取的长度(可能小于您要求的长度),如果它在文件末尾,则返回0,在错误时返回-1。如果您不检查的返回值read,则有一个错误。请注意,并非所有错误都是致命的。
即使您正在使用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") ;
Run Code Online (Sandbox Code Playgroud)
通常,您不应在两次轮询之间尝试两次读取相同的文件描述符。否则,如果文件描述符上没有更多数据可用,第二个块可能会阻塞。取而代之的是,您应该读取一定数量的数据,但要准备read返回的数据少于请求的数量,然后返回轮询循环以查找现在可用的数据(如果在其他fd上,则可能是这样)一个没有可用的新数据,但另一个有)。
使用read方法通常是一次读取整个缓冲区,而不是一次读取单个字符。