【问题标题】:Under what circumstances does the read() syscall return 0?read() 系统调用在什么情况下返回 0?
【发布时间】:2023-03-31 04:12:01
【问题描述】:

我正在查看 Unix 中的 read 系统调用,它(至少在 Linux 中)具有以下签名:[1]

ssize_t read(int fd, void* buf, size_t count);

假设调用成功(即没有负返回值)并且count > 0(即缓冲区实际上可以存储非零字节数)。在什么情况下read() 会返回 0?我可以想到以下几点:

  • fd 引用常规文件并且已到达文件末尾时。
  • fd指管道、套接字或FIFO的接收端时,发送端已经关闭,管道/套接字/FIFO自身的缓冲区已经耗尽。
  • fd 指代位于ICANON 中的终端设备的从端时,Ctrl-D 在行缓冲区为空时已发送到主端。

我很好奇是否还有其他我不知道的情况,read() 将返回结果为 0。我特别感兴趣(由于原因)像最后一个上面的列表,其中read() 返回 0 一次,但随后在同一 FD 上调用 read() 可能会返回非零结果。如果一个答案只适用于某种风格的 Unix,我仍然有兴趣听到它。

[1] 我知道这个签名是针对 libc 包装器的,而不是实际的系统调用,但现在这并不重要。

【问题讨论】:

  • 如果在上次读取返回 0 后附加了文件,则常规文件会发生这种情况。
  • 0 始终被认为是“文件结尾”。只是对于某些类型的流,这可能是暂时的情况。
  • "在没有错误的情况下,或者如果没有执行错误检测,read() 函数将返回零并且没有其他结果。"1
  • @vv01f 只有nbyte == 0
  • 在 z/OS 中: (1) 如果物理文件系统不支持从目录进行简单读取,则 read() 将在用于目录时返回 0。 (2) 如果读操作的起始位置在文件末尾或超出,read()返回0。doc

标签: linux unix system-calls


【解决方案1】:
  • 如果物理文件系统不支持从目录进行简单读取,则 read() 用于目录时将返回 0。
  • 如果没有进程打开管道进行写入,read() 返回 0 表示文件结束。
  • 如果流套接字上的连接断开,但没有可用数据,则 read() 函数返回 0 字节作为 EOF。

【讨论】:

  • 我在这里唯一没有提到的是目录支持的 fds 上的空读取(据我所知,它也不是可移植的;一些不起眼的 Unices 返回东西来自目录上的 read() 。很抱歉,但这不值得 IMO +200 赏金。
  • @StefanMajewsky 除了你的第 2 点和第 3 点的特殊情况,我认为没有其他情况。
  • 我不反对。
【解决方案2】:

通常返回值0 总是意味着文件结束。但是,如果您将 0 指定为要读取的字节数,它将始终返回 0,除非检测到错误。

终端设备是一种特殊情况。如果终端处于熟化模式,键入 Control-d 会告诉设备驱动程序立即从任何待处理的read() 返回输入编辑缓冲区中的任何内容,而不是等待用户输入新队。如果缓冲区为空,则会导致零长度读取。这就是应用程序自动将在行首键入 EOF 字符视为 EOF 的方式。

【讨论】:

  • 问题中已经提到了这两个(指定了count > 0,并且项目符号3是tty上的C-d)。
猜你喜欢
  • 2021-08-14
  • 1970-01-01
  • 1970-01-01
  • 2012-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多