【问题标题】:Is it safe to use fgets() as non-blocking call in C?在 C 中使用 fgets() 作为非阻塞调用是否安全?
【发布时间】:2017-02-28 22:24:03
【问题描述】:

从这个post 听起来fgets() 是一个阻塞调用,但是,this 手册页显示如果设置为非阻塞,它将返回NULLerrno 将是EWOULDBLOCK 如果没有数据可以读取,那么我的假设是确实可以将其用作非阻塞。

我知道select()和朋友们,我只是想知道将其用作非阻塞是否安全?如果不是,那是什么原因?

【问题讨论】:

  • 定义“安全”。如果您正确使用它,那么是的,它是“安全的”。
  • 正常使用。听起来好像将其用作非阻塞是不正确的,但如果是这样,那么我想这就回答了这个问题。谢谢
  • 如果底层 fd 是常规文件(不是管道、tty、fifo 或套接字),即使您将其设置为非阻塞,在 Linux 上读取仍将阻塞。
  • 感谢您澄清这一点。它正在从标准输入读取。
  • 如果您在重定向下运行程序,Stdin 可能是常规文件。

标签: c fgets nonblocking


【解决方案1】:

我只是想知道将其用作非阻塞是否安全?如果不是,那是什么原因?

这取决于您所说的“安全”是什么意思。 C 本身没有非阻塞 I/O 的概念,因此如果您编写的代码必须具有广泛的可移植性,那么即使假设非阻塞 I/O 是可用的替代方案也是不安全的。

如果您正在为更具体的环境(例如 POSIX 环境)编写代码,那么您可能能够依赖非阻塞 I/O 的可用性,但您应该考虑该环境的规范以确定什么当您指定给它的文件在某种相关意义上处于非阻塞模式时,您可能会从 fgets() 中得到预期的行为。 POSIX 确实指定 fgets() 在与 fgetc() 相同的条件下失败并出现错误,其中之一是

O_NONBLOCK 标志为文件描述符底层流设置,线程将在 [fgets()] 操作中延迟。

在这种情况下,如果您将“安全”定义为“由 POSIX 指定”,那么是的,当底层打开文件描述处于非阻塞模式时,依靠 fgets() 不阻塞是安全的。

@R.. 在 cmets 中断言,对处于非阻塞模式的文件使用 stdio 函数可能会导致数据丢失。这是有道理的,但我还没有找到这个断言的基础。但是,我不准备在这一点上反驳他,因此,同样,您提出的建议是否“安全”取决于您使用该术语的含义。

【讨论】:

  • POSIX 确实指定了。 EAGAINfgetc 的强制错误(根据它定义了fgets),并且在错误时,设置ferror 指示符并且未指定缓冲区的状态和文件位置。因此,尝试在非阻塞模式下使用 stdio,您会丢失数据
  • @R..,没错。也就是说,fgets() 的文档参考了fgetc() 的错误情况,我忽略了这一点。它的一般 行为不是根据fgetc() 定义的。我会及时更新我的​​答案。
  • @R.. 抱歉,您的意思是什么,您会丢失数据?这是否意味着在某些实现中它会起作用,而在某些实现中您不会在下一次可用读取时获得您期望的数据?
  • @JohnBollinger 感谢您的回答,现在说得通了。
  • @R..: 调用clearerr() 应该可以清除错误,但你是对的,你不知道在函数检测到错误时缓冲数据发生了什么.也许也将流更改为无缓冲?
猜你喜欢
  • 1970-01-01
  • 2017-02-26
  • 2011-02-13
  • 2011-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 2020-11-07
相关资源
最近更新 更多