Kqueue(边触发):短读是否意味着读写准备丢失?

时间:2021-08-29 02:30:48

When working with Linux epoll in edge triggered mode (EPOLLET), and a read/write fails with EAGAIN/EWOULDBLOCK, it means that read/write-readiness was lost, and that a new readiness event is guaranteed to be made available via epoll_wait() as soon as readiness is regained.

当在edge触发模式(EPOLLET)中使用Linux epoll时,当EAGAIN/ eif锁出现读/写失败时,这意味着读/写准备丢失,一旦准备就绪恢复,新的准备事件将通过epoll_wait()保证可用。

Additionally, when working with Linux epoll in edge triggered mode, and a nonblocking stream-mode socket, and provided that we registered interest in EPOLLRDHUP events, and that an EPOLLRDHUP event was not already received, a short read/write (return value less than requested size) also means loss of read/write-readiness, and we can still rely on a new readiness notification when readiness is regained, even though no read/write ever failed with EAGAIN/EWOULDBLOCK.

此外,当使用Linux epoll边缘触发模式,和一个非阻塞套接字流模式,并提供我们注册兴趣EPOLLRDHUP事件,EPOLLRDHUP事件不是已经收到,一个简短的读/写(返回值小于请求的大小)也意味着失去读/ write-readiness,我们仍然可以依靠一个新的准备就绪通知准备恢复时,即使没有读/写EAGAIN / EWOULDBLOCK失败。

Similarly, when working with Kqueue (macOS/FreeBSD) in edge triggered mode (EV_CLEAR), and a read/write fails with EAGAIN/EWOULDBLOCK, it means that read/write-readiness was lost, and that a new readiness event is guaranteed to be made available via kevent() as soon as readiness is regained.

类似地,当使用边缘触发模式(EV_CLEAR)处理Kqueue (macOS/FreeBSD)时,当使用EAGAIN/ eif dblock进行读/写失败时,这意味着读/写准备丢失了,一旦准备就绪恢复,新的准备就绪事件将通过kevent()保证可用。

Question: When working with Kqueue in edge-triggered mode, and a nonblocking stream-mode socket, and provided that we registered interest in EV_EOF events, and that an EV_EOF event was not already received, is there a similar guarantee, that a short read/write means loss of read/write-readiness, and that a new readiness event is guaranteed to be produced when readiness is regained?

问题:当处理Kqueue在边沿触发模式下,和一个非阻塞套接字流模式,并提供我们注册兴趣EV_EOF事件,EV_EOF事件不是已经收到,是否有类似的保证,短读/写意味着读/ write-readiness丧失,一个新的准备就绪事件是保证生产准备时恢复了吗?

EDIT: Note: Knowing that a short read means loss of read-readiness allows me (in the general case) to avoid a redundant invocation of read() just to get the EAGAIN/EWOULDBLOCK failure.

编辑:注意:知道短读意味着失去读准备,使我(在一般情况下)避免重复调用read(),从而获得EAGAIN/ eif dblock失败。

The meaning of a short read/write in the context of Linux epoll, follows from this comment in epoll(7) man page:

在Linux epoll上下文中,短读/写的含义来自epoll(7) man页面中的这条评论:

For stream-oriented files (e.g., pipe, FIFO, stream socket), the condition that the read/write I/O space is exhausted can also be detected by checking the amount of data read from / written to the target file descriptor. For example, if you call read(2) by asking to read a certain amount of data and read(2) returns a lower number of bytes, you can be sure of having exhausted the read I/O space for the file descriptor. The same is true when writing using write(2). (Avoid this latter technique if you cannot guarantee that the monitored file descriptor always refers to a stream-oriented file.)

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

1 个解决方案

#1


0  

You ask about "Kqueue in edge-triggered mode", but the kqueue documentation does not use that terminology. I think you must mean that you have enabled the EV_CLEAR flag for the event in question, with the effect that

您会问“Kqueue in the edge-trigger mode”,但Kqueue文档没有使用这个术语。我想您一定是说您已经为相关事件启用了EV_CLEAR标志,其效果是

After the event is retrieved by the user, its state is reset.

在用户检索事件之后,它的状态被重置。

(BSD documentation for kqueue())

(BSD文档kqueue())

Furthermore, you stipulate that the program has

此外,您还规定该程序有

registered interest in EV_EOF events, and that an EV_EOF event was not already received

对EV_EOF事件的注册兴趣,并没有收到EV_EOF事件。

but EV_EOF is not an event in its own right; rather, it is a flag that some of the available filters will set when appropriate, especially EVFILT_READ.

但是EV_EOF本身并不是一个事件;相反,它是一些可用过滤器将在适当时设置的标志,特别是EVFILT_READ。

Anyway, the core of your question is

不管怎样,你的问题的核心是

is there a similar guarantee, that a short read/write means loss of read/write-readiness, and that a new readiness event is guaranteed to be produced when readiness is regained?

是否有类似的保证,短读/写意味着失去读/写准备度,当准备度恢复时保证产生新的准备事件?

As far as I can determine, there is no guarantee that a short read signals loss of read readiness, neither for BSD nor for Linux. Indeed, the Linux docs for read(2) specifically call out receipt of a signal as a possible alternative reason for a short read.

就我所知,对于BSD和Linux来说,短读信号都不能保证失去读取准备。实际上,用于read(2)的Linux文档明确地将接收信号作为短读的可能替代原因。

Moreover, the usage model the Linux epoll() docs recommend for non-blocking file descriptors in edge-triggered mode is to read repeatedly until a read fails with EAGAIN, using that as the indication of loss of readiness prior to end-of-file. I recommend following the same policy with the kqueue system for events that have EV_CLEAR in effect.

此外,Linux epoll()文档建议在边缘触发模式下使用非阻塞文件描述符的使用模型是重复读取,直到EAGAIN出现读取失败,使用EAGAIN作为在文件结束前准备丢失的指示。我建议对实际具有EV_CLEAR的事件使用kqueue系统执行相同的策略。

I recognize that you hoped to save one read() call by stopping upon a short read, but I think that presents a bona fide risk of the process least of leaving incoming data streams unserviced indefinitely. Furthermore, your concern is premature unless you've determined that those extra reads are responsible for a measurable, unacceptable performance drain.

我认识到,您希望在短读时停止一次read()调用,但我认为这确实存在一定的风险,即至少要无限期地不为传入的数据流提供服务。此外,您的担心还为时过早,除非您确定这些额外的读取将导致可度量的、不可接受的性能消耗。

#1


0  

You ask about "Kqueue in edge-triggered mode", but the kqueue documentation does not use that terminology. I think you must mean that you have enabled the EV_CLEAR flag for the event in question, with the effect that

您会问“Kqueue in the edge-trigger mode”,但Kqueue文档没有使用这个术语。我想您一定是说您已经为相关事件启用了EV_CLEAR标志,其效果是

After the event is retrieved by the user, its state is reset.

在用户检索事件之后,它的状态被重置。

(BSD documentation for kqueue())

(BSD文档kqueue())

Furthermore, you stipulate that the program has

此外,您还规定该程序有

registered interest in EV_EOF events, and that an EV_EOF event was not already received

对EV_EOF事件的注册兴趣,并没有收到EV_EOF事件。

but EV_EOF is not an event in its own right; rather, it is a flag that some of the available filters will set when appropriate, especially EVFILT_READ.

但是EV_EOF本身并不是一个事件;相反,它是一些可用过滤器将在适当时设置的标志,特别是EVFILT_READ。

Anyway, the core of your question is

不管怎样,你的问题的核心是

is there a similar guarantee, that a short read/write means loss of read/write-readiness, and that a new readiness event is guaranteed to be produced when readiness is regained?

是否有类似的保证,短读/写意味着失去读/写准备度,当准备度恢复时保证产生新的准备事件?

As far as I can determine, there is no guarantee that a short read signals loss of read readiness, neither for BSD nor for Linux. Indeed, the Linux docs for read(2) specifically call out receipt of a signal as a possible alternative reason for a short read.

就我所知,对于BSD和Linux来说,短读信号都不能保证失去读取准备。实际上,用于read(2)的Linux文档明确地将接收信号作为短读的可能替代原因。

Moreover, the usage model the Linux epoll() docs recommend for non-blocking file descriptors in edge-triggered mode is to read repeatedly until a read fails with EAGAIN, using that as the indication of loss of readiness prior to end-of-file. I recommend following the same policy with the kqueue system for events that have EV_CLEAR in effect.

此外,Linux epoll()文档建议在边缘触发模式下使用非阻塞文件描述符的使用模型是重复读取,直到EAGAIN出现读取失败,使用EAGAIN作为在文件结束前准备丢失的指示。我建议对实际具有EV_CLEAR的事件使用kqueue系统执行相同的策略。

I recognize that you hoped to save one read() call by stopping upon a short read, but I think that presents a bona fide risk of the process least of leaving incoming data streams unserviced indefinitely. Furthermore, your concern is premature unless you've determined that those extra reads are responsible for a measurable, unacceptable performance drain.

我认识到,您希望在短读时停止一次read()调用,但我认为这确实存在一定的风险,即至少要无限期地不为传入的数据流提供服务。此外,您的担心还为时过早,除非您确定这些额外的读取将导致可度量的、不可接受的性能消耗。