Linux 在 select() 之后 read() 会阻塞吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5351994/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Will read() ever block after select()?
提问by Basilevs
I'm reading a stream of data through TCP/IP socket. The stream load is very uneven. Sometimes large bulks of data arrive every second, sometimes no data come for an hour. In the case of long inactivity period (no data from remote server, but connection is still online) my program should take some actions.
我正在通过 TCP/IP 套接字读取数据流。流负载非常不均匀。有时每秒都有大量数据到达,有时一个小时内没有数据。在长时间不活动的情况下(没有来自远程服务器的数据,但连接仍然在线)我的程序应该采取一些行动。
I'm implementing a timeout using a select(). It tells me if there are data ready, but I don't know exactly how much can I read without causing read() to block. Blocking is unacceptable as it may last far longer than the timeout I need.
我正在使用 select() 实现超时。它告诉我是否有数据准备好,但我不知道在不导致 read() 阻塞的情况下我可以读取多少。阻塞是不可接受的,因为它的持续时间可能比我需要的超时时间长得多。
For the sake of efficiency, stream is read into large buffer and read() call is provided with that buffer size.
为了效率起见,流被读入大缓冲区,并且 read() 调用提供了该缓冲区大小。
Will read() block after select() if the buffer to be filled is greater than amount of data available right now in the socket?
如果要填充的缓冲区大于套接字中当前可用的数据量, read() 会在 select() 之后阻塞吗?
采纳答案by Damon
Actually it should not block (that is what select() is for!), but in fact, it might, exceptionally. Normally, read() should return up to the maximum number of bytes that you've specified, which possibly includes zero bytes (this is actually a valid thing to happen!), but it should never block after previously having reported readiness.
实际上它不应该阻塞(这就是 select() 的用途!),但实际上,它可能会异常。通常, read() 应该返回您指定的最大字节数,其中可能包括零字节(这实际上是一个有效的事情!),但它不应该在先前报告就绪后阻塞。
Nevertheless, see the Linux selectman page:
不过,请参阅 Linux选择手册页:
Under Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may be safer to use O_NONBLOCK on sockets that should not block.
在 Linux 下, select() 可能会将套接字文件描述符报告为“ready for reading”,但随后的读取会阻塞。例如,当数据已到达但检查时校验和错误并被丢弃时,可能会发生这种情况。可能还有其他情况,其中文件描述符被虚假地报告为就绪。因此,在不应阻塞的套接字上使用 O_NONBLOCK 可能更安全。
回答by Vlad H
No, read()
will read up to specified size and will return the actual bytes read, which can be less.
不,read()
将读取到指定的大小并返回读取的实际字节数,可能会更少。
回答by ony
There is O_NONBLOCK
which can be set by fcntl
/F_SETFL
and should result in non-blocking read
.
有O_NONBLOCK
哪些可以由fcntl
/设置F_SETFL
并且应该导致非阻塞read
。
回答by MKo
You can use recv() which doesn't block by default( if the flag MSG_WAITALL is not specified)
您可以使用默认情况下不阻塞的 recv()(如果未指定标志 MSG_WAITALL)
回答by Duck
A blocking file descriptor will block on read() until there is something to read - could be one byte or your entire request. A non-blocking descriptor won't block on read() if there is nothing to read. Select() is not read(). It basically puts the process to sleep and monitors the file descriptor(s), including non-blocking descriptors. When there is activity on one of the descriptors (or the timeout period expires) select returns and you can read your data, or do something else in the case of the timeout.
阻塞文件描述符将在 read() 上阻塞,直到有内容要读取 - 可能是一个字节或您的整个请求。如果没有要读取的内容,则非阻塞描述符不会在 read() 上阻塞。Select() 不是 read()。它基本上使进程进入睡眠状态并监视文件描述符,包括非阻塞描述符。当其中一个描述符有活动(或超时期限到期)时,选择返回,您可以读取数据,或者在超时的情况下执行其他操作。
So you have two separate issues. (1) You want to "take some actions" when there is no data. That's the select timeout. (2) Once you have data (notified by select) you don't want to block on a read. That's the non-blocking mode. When you get EAGAIN on the non-blocking read you loop back to the select and/or "take some actions" and loop back to select.
所以你有两个不同的问题。(1) 当没有数据时,你想“采取一些行动”。这就是选择超时。(2) 一旦你有数据(通过 select 通知),你就不想阻止读取。这就是非阻塞模式。当您在非阻塞读取上获得 EAGAIN 时,您将循环回选择和/或“采取一些操作”并循环回选择。