如果一个 I/O 函数不能因 EINTR 而失败,这是不是意味着它永远不会阻塞?

Posted

技术标签:

【中文标题】如果一个 I/O 函数不能因 EINTR 而失败,这是不是意味着它永远不会阻塞?【英文标题】:If an I/O function cannot fail with EINTR, does that mean it never blocks?如果一个 I/O 函数不能因 EINTR 而失败,这是否意味着它永远不会阻塞? 【发布时间】:2015-07-12 11:53:05 【问题描述】:

例如,考虑fdopen。我一直在想,如果文件描述符参数引用管道或套接字,是否有可能阻塞。谷歌搜索没有发现任何有用的东西。一方面,在我看来它不应该阻塞,因为它只是将流与文件描述符“关联”。另一方面,我想知道实现是否有许可在 fdopen 调用时预填充缓冲区,如果新打开的管道或套接字还没有可供读取的数据,这可能会阻塞。

可能的错误是EMFILEEBADFEINVALENOMEM。我假设任何阻塞 I/O 函数都可能被信号中断,因此如果 fdopen 可能阻塞,那么 EINTR 也将作为可能的错误给出。既然不是这样,我可以假设fdopen 永远不会阻塞吗?这是否也适用于其他 I/O 功能?

【问题讨论】:

【参考方案1】:

fdopen() 是一个 libc 调用,它使用诸如 fcntl() 之类的各种系统调用来检查文件的状态。与 fdopen() 返回的相比,这些系统调用可以阻止和/或返回额外的错误代码。例如,fcntl() 可以阻塞并返回 EINTR。 fdopen() 的实现透明地处理可恢复的错误条件。

底线,fdopen() 可以阻塞,因为它至少使用了一个阻塞系统调用。同样的道理也适用于其他与 I/O 相关的 libc 函数。

【讨论】:

以上是关于如果一个 I/O 函数不能因 EINTR 而失败,这是不是意味着它永远不会阻塞?的主要内容,如果未能解决你的问题,请参考以下文章

Python标准异常

对 websocket 服务器的请求失败并出现 WebSocket I/O 错误:读取超时

Epoll原理解析

闪亮的应用程序因“参数 1(类型 'closure')不能被 'cat' 处理”而失败 - 这是啥意思?

Apollo Graphql 分页因限制而失败

Lambda 函数因无法导入模块“索引”而失败