- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
众所周知,某些阻塞调用,例如read
和write
将返回-1并将errno
设置为EINTR
,我们需要对此进行处理。
我的问题是:这是否适用于非阻塞调用,例如,将套接字设置为O_NONBLOCK
?
由于我已经阅读了一些文章和资料,所以说无阻塞调用并不需要为此烦恼,但是我发现没有权威性的参考。如果是这样,它是否适用于不同的实现?
最佳答案
对于该问题,我无法给出确切的答案,并且答案可能会因系统而异,但是我希望非阻塞套接字永远不会因EINTR
而失败。如果查看以下套接字功能bind()
,connect()
,send()
和receive()
的各种系统的手册页,或者在POSIX标准中查找这些内容,您会发现一些有趣的事情:除一个功能外,所有这些功能都可能返回-1
并将errno
设置为EINTR
。未记录为EINTR
失败的一个功能是bind()
。并且bind()
也是该列表中唯一在默认情况下永远不会阻止的功能。因此,似乎只有阻塞函数可能会因EINTR
而失败,包括read()
和write()
,但是如果这些函数从未阻塞,则它们也不会因EINTR
而失败;如果您使用O_NONBLOCK
,这些函数永远不会阻止。
从逻辑的角度来看,这也没有任何意义。例如。考虑到您正在使用阻塞I / O,并且您调用read()
并且此调用必须阻塞,但是在阻塞时,信号将发送到您的进程,因此读取请求被解除阻塞。系统应如何处理这种情况?声称read()
成功了吗?那将是一个谎言,它没有成功,因为没有读取任何数据。声称它确实成功了,但是读取了零字节数据?这也不正确,因为“零读取结果”用于指示流的末尾(或文件末尾),因此您的进程将假定未读取任何数据,因为文件已到达(或另一端的套接字/管道已关闭),事实并非如此。尚未到达文件末尾(或流末尾),如果再次调用read()
,它将能够返回更多数据。因此,这也是一个谎言。您期望该读取调用成功并读取数据,或者由于错误而失败。因此,在这种情况下,读取调用必须失败并返回-1
,但是系统应设置什么errno
值?所有其他错误值都表明文件描述符存在严重错误,但没有严重错误,表明这种错误也可能是谎言。这就是将errno
设置为EINTR
的原因,这意味着:“流没有任何问题。您的读取调用只是失败了,因为它被信号中断了。如果没有被中断,则它可能仍然成功,因此,如果您仍然需要这些数据,请重试。”
如果现在切换到非阻塞I / O,则不会出现上述情况。读取调用将永远不会阻塞,并且如果无法立即读取数据,它将失败,并显示错误EAGAIN
(POSIX)或EWOULDBLOCK
(非官方的,在Linux上都是相同的错误,只是它的替代名称),这意味着:“目前没有可用数据,因此您的读取调用将不得不阻塞并等待数据到达,但不允许阻塞,因此失败了。”因此,每种情况都可能出现错误。
当然,即使在非阻塞I / O的情况下,读调用也可能会被信号暂时中断,但是系统为什么要指出呢?每个函数调用,无论是系统函数还是用户编写的函数,都可能会被信号暂时中断,实际上每个信号都不例外。如果系统必须在发生这种情况时通知用户,则所有系统功能都可能由于EINTR
而失败。但是,即使发生信号中断,功能也通常会一直执行到最后,这就是为什么这种中断无关紧要的原因。错误EINTR
用于告诉调用者,由于信号中断,未执行他所请求的操作,但是在非阻塞I / O的情况下,没有理由该函数不应执行读取或读取操作。写入请求,除非不能立即执行,但是可以通过适当的错误来指示。
为了证实我的理论,我看了一下MacOS(10.8)的内核,该内核仍主要基于FreeBSD内核,似乎证实了人们的怀疑。如果当前无法进行读取调用,因为没有可用数据,则内核会检查文件描述符标志中的O_NONBLOCK
标志。如果设置了此标志,则它立即失败,并显示EAGAIN
。如果未设置,则通过调用名为msleep()
的函数使当前线程进入睡眠状态。函数是documented here(正如我所说,OS X在其内核中使用了大量的FreeBSD代码)。此函数使当前线程进入睡眠状态,直到显式唤醒它(如果数据已准备就绪,可以读取)或达到超时(例如,您可以在套接字上设置接收超时)。但是,如果传递了信号,线程也会被唤醒,在这种情况下,msleep()
本身将返回EINTR
,而下一个更高的层将传递此错误。因此,是msleep()
会产生EINTR
错误,但是如果设置了O_NONBLOCK
标志,则首先不会调用msleep()
,因此无法返回此错误。
当然那是MacOS / FreeBSD,其他系统可能有所不同,但是由于大多数系统试图在这些API之间至少保持一定程度的一致性,因此,如果系统违反了这一假设,则非阻塞I / O调用永远不会失败由于EINTR
,这可能不是故意的,甚至在您举报时也可能得到解决。
关于nonblocking - EINTR和非阻塞调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14134440/
为了让我的代码几乎完全用 Jquery 编写,我想用 Jquery 重写 AJAX 调用。 这是从网页到 Tomcat servlet 的调用。 我目前情况的类似代码: var http = new
我想使用 JNI 从 Java 调用 C 函数。在 C 函数中,我想创建一个 JVM 并调用一些 Java 对象。当我尝试创建 JVM 时,JNI_CreateJavaVM 返回 -1。 所以,我想知
环顾四周,我发现从 HTML 调用 Javascript 函数的最佳方法是将函数本身放在 HTML 中,而不是外部 Javascript 文件。所以我一直在网上四处寻找,找到了一些简短的教程,我可以根
我有这个组件: import {Component} from 'angular2/core'; import {UserServices} from '../services/UserService
我正在尝试用 C 实现一个简单的 OpenSSL 客户端/服务器模型,并且对 BIO_* 调用的使用感到好奇,与原始 SSL_* 调用相比,它允许一些不错的功能。 我对此比较陌生,所以我可能会完全错误
我正在处理有关异步调用的难题: 一个 JQuery 函数在用户点击时执行,然后调用一个 php 文件来检查用户输入是否与数据库中已有的信息重叠。如果是这样,则应提示用户确认是否要继续或取消,如果他单击
我有以下类(class)。 public Task { public static Task getInstance(String taskName) { return new
嘿,我正在构建一个小游戏,我正在通过制作一个数字 vector 来创建关卡,该数字 vector 通过枚举与 1-4 种颜色相关联。问题是循环(在 Simon::loadChallenge 中)我将颜
我有一个java spring boot api(数据接收器),客户端调用它来保存一些数据。一旦我完成了数据的持久化,我想进行另一个 api 调用(应该处理持久化的数据 - 数据聚合器),它应该自行异
首先,这涉及桌面应用程序而不是 ASP .Net 应用程序。 我已经为我的项目添加了一个 Web 引用,并构建了各种数据对象,例如 PayerInfo、Address 和 CreditCard。但问题
我如何告诉 FAKE 编译 .fs文件使用 fsc ? 解释如何传递参数的奖励积分,如 -a和 -target:dll . 编辑:我应该澄清一下,我正在尝试在没有 MSBuild/xbuild/.sl
我使用下划线模板配置了一个简单的主干模型和 View 。两个单独的 API 使用完全相同的配置。 API 1 按预期工作。 要重现该问题,请注释掉 API 1 的 URL,并取消注释 API 2 的
我不确定什么是更好的做法或更现实的做法。我希望从头开始创建目录系统,但不确定最佳方法是什么。 我想我在需要显示信息时使用对象,例如 info.php?id=100。有这样的代码用于显示 Game.cl
from datetime import timedelta class A: def __abs__(self): return -self class B1(A):
我在操作此生命游戏示例代码中的数组时遇到问题。 情况: “生命游戏”是约翰·康威发明的一种细胞自动化技术。它由一个细胞网格组成,这些细胞可以根据数学规则生存/死亡/繁殖。该网格中的活细胞和死细胞通过
如果我像这样调用 read() 来读取文件: unsigned char buf[512]; memset(buf, 0, sizeof(unsigned char) * 512); int fd;
我用 C 编写了一个简单的服务器,并希望调用它的功能与调用其他 C 守护程序的功能相同(例如使用 ./ftpd start 调用它并使用 ./ftpd stop 关闭该实例)。显然我遇到的问题是我不知
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
我希望能够从 cmd 在我的 Windows 10 计算机上调用 python3。 我已重新安装 Python3.7 以确保选择“添加到路径”选项,但仍无法调用 python3 并使 CMD 启动 P
我是一名优秀的程序员,十分优秀!