我需要了解
EAGAIN
和 EWOULDBLOCK
之间的区别,因为我看到许多源代码仅针对 EAGAIN
进行检查(可能这两个代码代表相同的数字,请在此处纠正我)。
我的部分知识: 对于阻塞套接字,如果发送方缓冲区已满并且接收方没有接收任何数据,如果调用
send()
,发送方将被挂起。这是因为一旦接收器读取数据,其在缓冲区中使用的空间就可用于新数据。如果您的套接字处于“非阻塞”模式,则“send()”将失败并显示“EAGAIN”或“EWOULDBLOCK”。
他们总是相同的数字还是在任何情况下需要对他们进行区别对待?
简而言之:它们几乎总是相同的值,但为了可移植性,建议检查这两个值(并以相同的方式处理这两个值)。
对于大多数系统,
EAGAIN
和 EWOULDBLOCK
是相同的。 只有少数系统不同,您可以看到这些系统的列表在此答案中。
甚至 errno 手册页也提到它们“可能是相同的[值]”。
然而,历史上,
EWOULDBLOCK
被定义为“操作将阻塞”——也就是说,操作would已经阻塞,但描述符被置于非阻塞模式。 EAGAIN
最初表示“临时资源短缺导致操作无法进行”。 gnu 文档使用的示例是当没有足够的资源来fork()
时。 由于预计资源短缺是暂时的,因此后续尝试执行该操作可能会成功(因此称为“再次”)。
实际上,这种类型的临时资源短缺并不常见(但当它们确实发生时相当严重)。
大多数系统将这些值定义为相同的,不这样做的系统将来会变得越来越不常见。尽管如此,出于可移植性的原因,您应该检查这两个值,但也应该以相同的方式处理这两个错误。 正如GNU文档所述:
可移植性注意事项:在许多较旧的 Unix 系统中... [EWOULDBLOCK 是] 与 EAGAIN 不同的明显错误代码。为了使您的程序可移植,您应该检查这两个代码并对它们进行相同的处理。
它们的功能相同。这两个不同名称的历史渊源可以追溯到 20 世纪 80 年代。 EWOULDBLOCK 用于 Unix 的 BSD/Sun 变体,EAGAIN 是 AT&T System V 错误代码。
对于特定系统上编译的二进制文件,代码应该具有相同的值。在包含文件中定义这两个名称的原因是为了源代码的可移植性。
include/uapi/asm-generic/errno.h
文件中:
#define EWOULDBLOCK EAGAIN /* Operation would block */