首页 文章

使用read()函数时检查EOF

提问于
浏览
1

这是我第一次使用文件描述符进行阅读,现在我已经通过试验和错误测试了大约3个小时,而且我几乎让我的读者工作了!我只需要在命名管道上检查EOF时需要一些帮助 .

好的,所以我打开一个(好多个)命名管道,如下所示:

fds[j].fd = open(pipeNameo, O_RDWR) ; // storing it into my file descriptor array

然后我轮询命名管道以查看是否有任何事情发生(轮询在循环内):

int ret = poll(fds, numOfPipesUsed, timeout_msecs);

当某些事情发生时,我通过将写入的文件描述符发送到此函数来处理文件:

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 ;
}

一切都很好,除了 the read() function gets stuck (waiting for a return I imagine) once all characters have already been read. 应该是EOF . 我需要能够检查EOF .

我尝试了一种解决方法,通过计算读取的字符数来阻止我的程序读取(因为我知道输入的大小),并且它会起作用,唯一的事情就是当最后一个字符后面有一个空格它导致我的循环poll返回1并在剩余的空间(无效输入)上再次运行 processFile() 以进行读取 .

请帮忙 :')

输入只是一个数字矩阵,如下所示:

0 1 1
2 0 3
1 0 0

3 回答

  • 1

    您需要打开非阻塞,因为管道将等待数据变为可用:

    fds[j].fd = open(pipeNameo, O_RDWR | O_NONBLOCK);
    
  • 2

    您应该首先确保实际上是在管道上命中文件末尾 .

    当您打开FIFO(命名管道的另一个名称)进行读取时,该进程将等待另一个进程打开它以进行写入和写入操作 . 然后它将继续等待更多输入,直到所有打开它的进程都关闭它 .

    您可以使用mkfifocat在几个终端窗口中测试:

    $ mkfifo test-fifo
    $ cat test-fifo     # This is the reading process and will wait for data to read
    

    在另一个终端:

    $ cat > test-fifo   # This is the writing process; type here and see it above
    

    现在,如果您关闭写入过程,读取过程将退出,因为它已经到达文件的末尾 .

    但是,如果打开两个写入进程,并且只退出一个,则FIFO将保持打开状态,读取结束将不会结束,直到您关闭它们 .

    因此,一个很容易犯错误的可能性就是让FIFO打开以便在某处写入,因此读取端永远不会得到文件结束条件 . 需要注意的一件事是,如果这个过程本身也有FIFO打开写入,或者如果产生数据的任何过程只是保持管道打开而不是在它完成后关闭它 .

    如果您无法确定进程是否已打开管道进行写入,请尝试使用fuserlsof来标识可能打开它的任何进程 .

    您的代码的其他一些评论,也可能是问题:

    char buf[10] ;
    
    read(fd, buf, 1) ;
    char curr = buf[0] ;
    while (curr != EOF)
    

    这不是你如何确定你是否使用低级,无缓冲的read原语命中文件的末尾;这就是你用fgetc这样的缓冲stdio操作的方法 . 使用 read ,您可以调用所需的长度来读取它,并返回它可以读取的数量(可能小于您要求的长度),如果它位于文件的末尾,则返回0,出错时返回-1 . 如果您没有检查 read 的返回值,则表示您有错误 . 请注意,并非所有错误都是致命的 .

    即使你使用 fgetc ,这个代码也是错误的 . fgetc 返回一个int,而不是一个char,因此它可以返回全部字符值以及EOF的sentinel值 .

    printf("BEFORE\n"); // Gets stuck here when EOF, this is the string of output
        read(fd, buf, 1) ;
        printf("AFTER\n") ;
    

    在调用poll之间,通常不应尝试两次读取相同的文件描述符;否则,如果文件描述符上没有更多可用数据,则第二个可以阻止 . 相反,您应该读取一定数量的数据,但要准备 read 以返回少于您请求的数据,然后返回轮询循环以找出现在可用的数据(可能在不同的fd上,如果这个没有新的数据,但另一个没有 .

    使用 read 的方法通常是一次读取整个缓冲区,而不是一次读取一个字符 .

  • 4

    读取的返回值0表示EOF .

相关问题