Skip to content

select/poll应该是同步阻塞,epoll是同步非阻塞的 #194

Closed
@LeroChen

Description

@LeroChen
No description provided.

Activity

CyC2018

CyC2018 commented on Apr 13, 2018

@CyC2018
Owner

@LeroChen 我明天再认真查阅一下相关资料,如果您有比较详细的资料的话,麻烦分享一下。

NutshellySima

NutshellySima commented on Apr 15, 2018

@NutshellySima
Contributor

@CyC2018

(参考资料见最后,已用方括号标出)

总的讨论

所有I/O多路复用操作都是同步的,涵盖select/poll[2][4]
阻塞/非阻塞是相对于同步I/O来说的,与异步I/O无关。
select/poll/epoll本身是同步的,可以阻塞也可以不阻塞。

Select:

关于Select是否阻塞:

在使用int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)函数时,可以设置timeval决定该系统调用是否阻塞[5]

If both fields of the
       timeval structure are zero, then select() returns immediately.  (This
       is useful for polling.)  If timeout is NULL (no timeout), select()
       can block indefinitely.

[《Linux/UNIX系统编程手册》Michael Kerrisk著 P1094]
tim 20180415181145

Poll:

关于Poll是否阻塞:

在使用int poll(struct pollfd *fds, nfds_t nfds, int timeout)函数获取信息时,可以通过指定timeout的值来决定是否阻塞[6](当timeout<0时,会无限期阻塞;当timeout=0时,会立即返回)。

Specifying a negative value
       in timeout means an infinite timeout.  Specifying a timeout of zero
       causes poll() to return immediately, even if no file descriptors are
       ready.

[《Linux/UNIX系统编程手册》Michael Kerrisk著 P1099]
tim 20180415181739

Epoll:

关于Epoll是否阻塞:

在使用epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)函数来获取是否有发生变化/事件的文件描述符时,可以通过指定timeout来指定该调用是否阻塞(当timeout=-1时,会无限期阻塞;当timeout=0时,会立即返回)。[1]

Specifying a timeout of -1 makes epoll_wait(2) wait indefinitely, 
while specifying a timeout equal to zero makes epoll_wait(2) to 
return immediately even if no events are available (return code equal 
to zero).

[《Linux/UNIX系统编程手册》Michael Kerrisk著 P1116]
tim 20180415175123

关于Epoll是否同步:

当前是否有发生变化/事件的文件描述符需要通过epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)显式地进行查询,因此不是异步;其他资料佐证了这一点[2]

参考资料

[1] http://man7.org/linux/man-pages/man2/epoll_wait.2.html
[2] https://www.zhihu.com/question/19732473/answer/26091478
[4] https://notes.shichao.io/unp/ch6/#synchronous-io-versus-asynchronous-io
[5] http://man7.org/linux/man-pages/man2/select.2.html
[6] http://man7.org/linux/man-pages/man2/poll.2.html
[7] 《Linux/UNIX系统编程手册》Michael Kerrisk著

所以正确的图表应该是:
54cb3f21-485b-4159-8bf5-dcde1c4d4c36

triumphaxe

triumphaxe commented on Apr 16, 2018

@triumphaxe

说的不错,关于这个问题产生过很多误解。一个常见的事实是通过同步非阻塞I/O实现了宏观层面的异步操作,结果这里的I/O也被往往误认为是异步的了。

yanjinbin

yanjinbin commented on Mar 18, 2019

@yanjinbin

nice

zhengrenjie

zhengrenjie commented on Feb 18, 2020

@zhengrenjie

👍

mengxunQAQ

mengxunQAQ commented on Feb 6, 2021

@mengxunQAQ

cool

xuqing-er

xuqing-er commented on Jun 17, 2021

@xuqing-er

我认为epoll是没有同步或者异步的,关键取决于下层使用的是什么。例如如果将epoll和libaio结合,来检测一个操作是否完成,那也是异步的,此时操作已经完成;而如果利用epoll检测Socket是否有可读的数据,检测之后仍然需要线程去读取,这应该就是同步的。我的看法可能有错误,望批评指正。

xuqing-er

xuqing-er commented on Jun 17, 2021

@xuqing-er

另外同步或者异步需要从不同的层次来看:例如对于一个异步的RPC请求,不用等待请求完成,但下层仍然可以使用同步的操作进行数据的传输

zgg2001

zgg2001 commented on Apr 1, 2022

@zgg2001

👍

enjoyDay

enjoyDay commented on Oct 11, 2022

@enjoyDay
wedvefv

wedvefv commented on Apr 6, 2023

@wedvefv

阻塞的本质是cpu因为要等待耗时的操作 (比如磁盘io,网络io) ,cpu每一纳秒都能做很多事的好么,所以懒得等。所以当前进程就会被放到一个等待队列中睡眠等着,同时释放cpu给别的进程; 如果io处理完了,随眠进程会被唤醒从等待队列拿出来继续执行。

所以select,poll,epoll大多数时候还是用阻塞模式,虽然能设置超时;因为你查到没有就绪的事件要cpu资源也没用,就应该就绪睡觉。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug错误

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @triumphaxe@wedvefv@yanjinbin@LeroChen@zhengrenjie

        Issue actions

          select/poll应该是同步阻塞,epoll是同步非阻塞的 · Issue #194 · CyC2018/CS-Notes