epoll 如何知道内核中的 socket 已经准备好?
How does epoll know socket is ready in kernel?
我在 epool
源代码中没有找到任何关于 epoll 如何知道套接字已准备好用于 read/write
的提示。
- epoll是否在内核中注册了一个
callback
?
- epool是否在内核中为
read/write
注册了一个signal
?
- 还是别的?
非常感谢。
简答
不仅用于 epoll
,而且通常用于 "blocking I/O"(例如,read()
系统调用使用相同的机制),内核使用 waitqueues
(不不要将它们与 workqueues
混淆,这是完全不同的机制)。如果您检查 ep_poll()
实施,它甚至会记录在评论中。
一些不太有趣的细节
为了让当前线程在等待队列中休眠,通常会使用 wait_event_interruptible()
调用。然而,epoll_wait
不会那样做。相反,它通过使用 __add_wait_queue_exclusive()
将自己添加到等待队列,使用 set_current_state(TASK_INTERRUPTIBLE)
使自己进入睡眠状态并检查在循环中被唤醒的原因,从而重新实现此调用将执行的操作。最终结果是相同的——当前线程将进入可中断睡眠状态,可以通过发送信号终止(在这种情况下 epoll_wait
将 return EINTR
)或被唤醒ep_poll_callback
通过 waitqueues
机制。
我在 epool
源代码中没有找到任何关于 epoll 如何知道套接字已准备好用于 read/write
的提示。
- epoll是否在内核中注册了一个
callback
? - epool是否在内核中为
read/write
注册了一个signal
? - 还是别的?
非常感谢。
简答
不仅用于 epoll
,而且通常用于 "blocking I/O"(例如,read()
系统调用使用相同的机制),内核使用 waitqueues
(不不要将它们与 workqueues
混淆,这是完全不同的机制)。如果您检查 ep_poll()
实施,它甚至会记录在评论中。
一些不太有趣的细节
为了让当前线程在等待队列中休眠,通常会使用 wait_event_interruptible()
调用。然而,epoll_wait
不会那样做。相反,它通过使用 __add_wait_queue_exclusive()
将自己添加到等待队列,使用 set_current_state(TASK_INTERRUPTIBLE)
使自己进入睡眠状态并检查在循环中被唤醒的原因,从而重新实现此调用将执行的操作。最终结果是相同的——当前线程将进入可中断睡眠状态,可以通过发送信号终止(在这种情况下 epoll_wait
将 return EINTR
)或被唤醒ep_poll_callback
通过 waitqueues
机制。