代码之家  ›  专栏  ›  技术社区  ›  Dmitry Dmitriev

Linux中流的魔力。什么时候结束?

  •  0
  • Dmitry Dmitriev  · 技术社区  · 5 年前

    今天早上5点我读了一篇关于 read 系统调用。事情对我来说变得非常清楚。

    ssize_t read(整数fd,void*buf,大小计数);

    *nix 就像操作系统变得惊人的简单。任何实体的文件接口,只要求从中写入一些日期 fd 通过 *buf 指针。网络,文件,流都一样。

    但有个问题出现了。 1) 流为空需要等待新数据。2) 流已关闭需要关闭程序。

    • 从中读取数据 STDIN 循环中,这个 标准物质 重定向者 pipe
    • 一些 text_data
    • 一点一点地读直到 EOF 在记忆中,或 0 阅读 打电话?

    这还不清楚。万一 endless continuous

    升级版

    • 阅读 保持程序执行并等待 count
    • 什么时候? 计数 阅读 写进 buf 执行仍在继续。
    • stream 已关闭 回报 0个 ,这是程序可能完成的信号。

    EOF公司 出现在 ?

    EOF公司 是一个常数,可以在 getc 功能

     while (ch != EOF)     { 
        /* display contents of file on screen */ 
        putchar(ch);  
    
        ch = getc(fp);   
     }
    

    阅读 这个 EOF公司 缓冲器 . 阅读 系统调用通过返回 . 而不是写作 EOF公司 data-area ,就像ak一样 getc公司 .

    EOF公司 getc公司

    0 回复  |  直到 5 年前
        1
  •  2
  •   K. A. Buhr    5 年前

    我们先来处理你原来的问题。请注意 man 7 pipe 应该提供一些有用的信息。

    假设我们将标准输入重定向到 pipe 呼叫,如:

    pipe(p);
    // ... fork a child to write to the output side of the pipe ...
    dup2(p[0], 0);  // redirect standard input to input side
    

    我们称之为:

    bytes = read(0, buf, 100);
    

    首先,请注意,这与直接从 p[0] ,所以我们可以这样做:

    pipe(p);
    // fork child
    bytes = read(p[0], buf, 100);
    

    那么,基本上有三种情况:

    1. 如果管道中有字节(即至少一个字节已经被写入,但尚未读取),那么读取调用将立即返回,并且它将返回最多可达100字节的所有可用字节。返回值将是读取的字节数,并且始终是介于1和100之间的正数。

    2. 如果管道为空(没有字节),并且输出端已关闭,则不会触及缓冲区,调用将立即返回,返回值为0。

    3. 否则,read调用将被阻塞,直到某些内容写入管道或关闭输出端,然后read调用将立即使用案例1和案例2中的规则返回。

    read() 调用返回0,这意味着已到达文件结尾,不需要更多字节。等待额外的数据会自动发生,在等待之后,您将获得数据(正返回值)或文件结束信号(零返回值)。在另一个进程写入一些字节,然后立即关闭(输出端)管道的特殊情况下,下一个进程 调用将返回最大为指定值的正值 count . 后继的 读取() 读取() 调用将返回0(因为管道已关闭)。

    计数 其他 比烟斗。而且,如果 计数 是0 读取() 计数 ,不管有多大 是。

    不管怎样,这样的想法是,类似于以下代码的东西应该可靠地从管道读取所有字节,直到关闭输出端,即使在Linux以外的平台上也是如此:

    #define _GNU_SOURCE 1
    #include <errno.h>
    #include <unistd.h>
    
    /* ... */
    
        while ((count = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)))) > 0) {
            // process "count" bytes in "buffer"
        }
        if (count == -1) {
            // handle error
        }
        // otherwise, end of data reached
    

    如果管道从未关闭(“无休止”或“连续”流),则 while 循环将永远运行,因为 read 将阻塞,直到它可以返回非零字节计数。

    关于你的 升级版 问题:

    阅读 计数 write 到管道,这将唤醒进程;当进程有机会运行时,它将返回可用的内容 高达 但不一定等于 字节。通常,这意味着如果另一个进程写入5个字节,则 read(fd, buffer, 100) 调用将返回5并继续执行。是的,如果 回报 0 ,一个 EOF 读取() 返回0,因此它将包含 打电话来。

    关于你的 评论:

    -1 . (从技术上讲,根据C99标准,它是一个等于负值的整数常量;也许有人知道平台不是 -1个 读取() 读取() returns-1如果出现错误,那么比较 读取() getc() getchar() 区分文件结尾和成功读取的字符。