unix 理解C(STDIN_FILENO)中的代码时出现问题

2lpgd968  于 2022-11-04  发布在  Unix
关注(0)|答案(1)|浏览(149)

我和我的朋友在理解代码方面有问题。我们不明白为什么在最后要检查nread是否为!= 1。如果有人能帮助我们,我们将非常高兴。

while ((nread = read(STDIN_FILENO, &c, 1)) != 1) {
        if (nread == -1 && errno != EAGAIN) quit("read");
    }
ybzsozfc

ybzsozfc1#

它使循环仅在读取成功时退出。
也就是说,代码有缺陷。
呼叫read会传回下列其中一项:

  • -1,出现错误。
  • 0,在EOF上。
  • [1,count],读取的字节数。

由于对read的此特定调用仅尝试读取一个字节,因此以下是可能返回的值:

  • -1,出现错误。
  • 0,在EOF上。
  • 1,在成功读取时。

那么,让我们把这个片段作为一个整体来看。

  • 如果出现EAGAIN以外的错误,则退出。
  • 如果出现错误EAGAIN,它将再次尝试。
  • 在eof上,它会再次尝试。
  • 在成功读取时,它将继续执行循环之外的操作。

这是有问题的,原因有二。

  • 它对EAGAIN的处理不正确

当没有数据可用时,非阻塞句柄返回EAGAIN。因此,这是一个忙等待循环(占用CPU)。这是不可接受的。
此外,如果句柄可以是套接字,则可以返回EWOULDBLOCK而不是EAGAIN。这根本不进行处理。

  • 它对EOF的处理不正确

在EOF时,它试图再次读取。这很糟糕。
现在,可以在某些句柄返回EOF后读取它们。具体来说,终端可以在返回EOF后重置它们的EOF状态。但不能保证STDIN就是终端。而且即使知道STDIN是终端,它仍然可以像其他句柄一样返回无休止的EOF流。

相关问题