【问题标题】:Is read() on a nonblocking socket "greedy" on platforms other than Linux (OSX, FreeBSD)?在 Linux(OSX、FreeBSD)以外的平台上,非阻塞套接字上的 read() 是否“贪婪”?
【发布时间】:2016-10-19 03:51:27
【问题描述】:

考虑在非阻塞流模式套接字 (SOCK_STREAM) 上对 read() 的以下调用:

ssize_t n = read(socket_fd, buffer, size);

假设远程对等方不会关闭连接,也不会关闭连接的写入部分(从本地角度来看,读取部分)。

在 Linux 上,这种情况下的短读取 (n > 0 && n < size) 意味着内核级读取缓冲区已用尽,并且立即后续调用通常会失败并显示 EAGAIN/EWOULDBLOCK(它会除非新数据设法在两次调用之间到达)。

换句话说,在 Linux 上,只要size 足够大,对read() 的调用将始终消耗立即可用的所有内容。

write() 类似,在Linux 上,短写入总是意味着内核级缓冲区已被填满,并且立即后续调用可能会失败并显示EAGAIN/EWOULDBLOCK

问题 1:这在 macOS/OSX 上是否也有保证?

问题 2:这在 FreeBSD 上是否也有保证?

问题 3:这是 POSIX 要求/保证的吗?

我知道这在 Linux 上是正确的,因为 epoll 手册页中的以下注释(第 7 节):

对于面向流的文件(如管道、FIFO、流套接字),也可以通过检查目标文件读/写的数据量来检测读/写I/O空间耗尽的情况描述符。例如,如果您通过请求读取一定数量的数据来调用 read(2),而 read(2) 返回的字节数较少,则可以确定文件描述符的读取 I/O 空间已用尽。使用 write(2) 写入时也是如此。 (如果你不能保证被监控的文件描述符总是指向一个面向流的文件,请避免使用后一种技术。)

编辑:作为问题的动机,考虑这样一种情况,您希望同时处理多个套接字上的输入,无论出于何种原因,您都希望通过依次完全耗尽每个套接字的内核缓冲区来做到这一点(即“深度优先”而不是“广度优先”)。这显然可以通过在准备就绪的套接字上重复读取来完成,直到它以EAGAIN/EWOULDBLOCK 失败,但是如果之前的读取很短,最后一次调用将是多余的,我们知道短读取是保证用尽。

【问题讨论】:

  • 问题 4:这在 Linux 上是否有保证?问题5:实际保证什么?你有什么问题?实际还会发生哪些其他行为?
  • 正如我所说,我相信它在 Linux 上得到保证,并且这种保证来自 epoll 手册页中提到的注释。如果你有理由相信我错了,请解释一下。
  • "believe" 是一个糟糕的编程基础。但是,我看不到会发生什么其他行为以及它会对应用程序逻辑产生什么变化。你想要数据,你轮询并阅读它。不能保证两个相邻的reads 将在抢占式多任务系统上连续执行。您的应用程序应始终假定数据在read 返回后立即到达。
  • @Olaf 我附加了一条说明,说明为什么我认为这个问题是相关的。你明白了吗?
  • @Olaf 我理解你的观点。在使用级别触发的轮询时,人们通常不会关心这一点,而只需在每次读取就绪通知时执行一次读取。然而,在边缘触发的情况下,必须耗尽内核缓冲区才能获得新的通知,并且您必须决定是否要以“深度优先”或“广度优先”的方式执行此操作。特别是对于“深度优先”的情况,尝试消除对read() 的一次调用是相关的。

标签: c macos sockets freebsd nonblocking


【解决方案1】:

Posix保证:

一旦数据可用,应立即将数据返回给用户。

...因此在您提到的所有其他平台上,还有 Windows、OS/2、NetWare...

任何其他实现都是没有意义的。

【讨论】:

  • “可用”是一个广泛的领域。人为地延迟任何系统的数据是毫无意义的。
  • @Olaf 正是如此。
  • @EJP 我不太确定该声明的预期含义,但我同意这可能是我正在寻求的保证。
  • @KristianSpangsege 它您正在寻求的保证。它说如果数据可用,则必须交付数据。因此,不允许只交付其中的一部分。没什么神秘的。
  • @EJP:如果没有这样的保证,我看不出它会对应用程序产生什么影响。操作系统中的内部进程仍然可以延迟帧的处理。
猜你喜欢
  • 1970-01-01
  • 2014-02-03
  • 2013-06-03
  • 2013-07-20
  • 1970-01-01
  • 2016-03-27
  • 2010-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多