c - Linux中STREAMS的魔力。什么时候结束?

标签 c linux stream

今天早上5点,我读了一篇关于read系统调用的文章。事情对我来说变得非常清楚。
ssize_t read(整数fd,void*buf,大小计数);
类似于cc>的操作系统的构建变得非常简单。对于任何实体的文件接口,只需通过指针从这个*nix接口将一些日期写入内存。网络,文件,流都一样。
但有个问题出现了。
如何区分两种情况?:
1)流为空需要等待新数据。2)流关闭需要关闭程序。
下面是一个场景:
在循环中从fd读取数据时,这个*bufSTDIN重定向。
一些STDIN出现
只是一点一点地读,直到记忆中有什么东西,或者是因为呼叫而有什么东西?
程序将如何理解:等待新的输入,还是退出?
这还不清楚。在pipetext_data流的情况下。
在与@Bailey Kocin交谈并阅读了一些文档后,我有了这种理解。如果我错了就帮我。
EOF保持程序执行并等待0比特数。
read出现比特数时endless将其写入continuous并继续执行。
read关闭时count返回count,这是程序可能完成的信号。
问题是read是否出现在buf中?
UPD2stream是一个常数,可以在read函数的输出中

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

    ch = getc(fp);   
 }

但在0的情况下,EOF值不出现在abuf中。EOF系统调用通过返回getc通知文件结束。而不是将read常数写入EOF,就像ak在buf的情况下一样。
read是在不同系统中变化的常数。用于0

最佳答案

我们先来处理你原来的问题。注意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);

那么,基本上有三种情况:
如果管道中有字节(即至少一个字节已经被写入,但尚未读取),那么读取调用将立即返回,并且它将返回最多可达100字节的所有可用字节。返回值将是读取的字节数,并且始终是介于1和100之间的正数。
如果管道为空(没有字节),并且输出端已关闭,则不会触及缓冲区,调用将立即返回,返回值为0。
否则,read调用将被阻塞,直到某些内容写入管道或关闭输出端,然后read调用将立即使用案例1和案例2中的规则返回。
因此,如果read()调用返回0,则表示已到达文件结尾,并且不需要更多字节。等待额外的数据会自动发生,在等待之后,您将获得数据(正返回值)或文件结束信号(零返回值)。在另一个进程写入一些字节,然后立即关闭(输出端)管道的特殊情况下,下一个read()调用将返回一个正值,直到指定的count。后续的read()调用将继续返回正值,只要有更多的数据要读取。当数据耗尽时,read()调用将返回0(因为管道已关闭)。
在Linux上,对于管道和任何阳性的count,以上都是正确的。除了管道,其他东西也可能有区别。此外,如果count为0,read()调用将始终立即返回,返回值为0。注意,如果您试图编写在Linux以外的平台上运行的代码,您可能需要更加小心。允许一个实现返回一个非零的字节数小于请求的字节数,即使管道中有更多的字节可用——这可能意味着存在一个实现定义的限制(因此无论您请求多少字节,都不会得到超过4096字节的结果,例如)或者这个实现定义了从一个调用到另一个调用的限制(因此,如果您在内核缓冲区的页面边界上请求字节,那么您只能得到页面的结尾或其他内容)。在Linux上,没有限制——无论count有多大,read调用总是返回count之前可用的所有内容。
不管怎样,这样的想法是,类似于以下代码的东西应该可靠地从管道读取所有字节,直到关闭输出端,即使在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将阻塞,直到它可以返回非零字节计数。
请注意,管道也可以设置为非阻塞模式,这会实质性地改变行为,但以上是默认的阻塞模式行为。
关于你的UPD问题:
是的,read保持程序执行直到数据可用,但是不,它不一定等待count字节。它将等待至少一个非空的write到管道,这将唤醒进程;当进程有机会运行时,它将返回所有可用的字节,但不一定等于count字节。通常,这意味着如果另一个进程写入5个字节,阻塞的read(fd, buffer, 100)调用将返回5并继续执行。是的,如果read返回0,则表示不再有要读取的数据,并且管道的写入端已关闭(因此不再有可用的数据)。不,缓冲区中不显示EOF值。只有读取的字节才会出现在那里,并且当read()返回0时不会触及缓冲区,因此它将包含read()调用之前的所有内容。
关于您的UPD2评论:
是的,在Linux上,EOF是一个常数,等于整数-1。(从技术上讲,根据C99标准,它是一个等于负值的整数常量;也许有人知道它不是-1的平台)这个常量不被read()接口使用,而且肯定不会写入缓冲区。如果出现错误,read()返回-1,那么将read()的返回值与EOF(而不是-1)进行比较将被认为是不好的做法。正如您所注意到的,EOF值实际上只用于C库函数,如getc()getchar()来区分文件结尾和成功读取的字符。

关于c - Linux中STREAMS的魔力。什么时候结束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56406603/

相关文章:

c - 在c中使用libcurl每n秒发送一次请求

c - 无线工具 : Converting network essid to char

linux - 复制到不同的用户剪贴板-Xorg linux

flutter - 如何在Sembast记录中的映射内监听单个值?

c - valgrind macos内存泄漏

c - 为什么我的 C 代码中的两个不同调用返回相同的结果?

linux - 为什么使用-rf?

linux - ANT 执行失败 : java. io.IOException : Cannot run program "cp ": java. io.IOException : error=2, 没有这样的文件或目录

c - "file pointer"、 "stream"、 "file descriptor"和... "file"之间的区别?

Android - 从所有正在运行的应用程序流式传输音频