使用read()函数时检查EOF

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)

Bri*_*ell 5

您首先应该确保您实际上在管道上碰到文件结尾。

当您打开FIFO(命名管道的另一个名称)进行读取时,该进程将等待,直到另一个进程打开它进行写入并写入内容。然后它将继续等待更多输入,直到所有可打开以供写入的进程将其关闭为止。

您可以使用mkfifo和在几个终端窗口中进行测试cat

$ 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以进行写入,或者无论产生了什么进程,则数据只是保持管道处于打开状态,而不是在完成后关闭管道。

如果您无法确定某个进程是否已打开要写入的管道,请尝试fuserlsof确定可能打开该管道的任何进程。

关于您的代码的其他一些注释,也可能是问题:

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方法通常是一次读取整个缓冲区,而不是一次读取单个字符。