Linux下epoll的边缘出发、水平触发

本文最后更新于2017年8月12日,已超过 1 年没有更新,如果文章内容失效,还请反馈给我,谢谢!

=Start=

缘由:

学习、提高需要

正文:

参考解答:

Level_triggered(水平触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据一次性全部读写完(如读写缓冲区太小),那么下次调用 epoll_wait()时,它还会通知你在上没读写完的文件描述符上继续读写,当然如果你一直不去读写,它会一直通知你!!!如果系统中有大量你不需要读写的就绪文件描述符,而它们每次都会返回,这样会大大降低处理程序检索自己关心的就绪文件描述符的效率!!!

Edge_triggered(边缘触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太小),那么下次调用epoll_wait()时,它不会通知你,也就是它只会通知你一次,直到该文件描述符上出现第二次可读写事件才会通知你!!!这种模式比水平触发效率高,系统不会充斥大量你不关心的就绪文件描述符!!!

阻塞IO:当你去读一个阻塞的文件描述符时,如果在该文件描述符上没有数据可读,那么它会一直阻塞(通俗一点就是一直卡在调用函数那里),直到有数据可读。当你去写一个阻塞的文件描述符时,如果在该文件描述符上没有空间(通常是缓冲区)可写,那么它会一直阻塞,直到有空间可写。以上的读和写我们统一指在某个文件描述符进行的操作,不单单指真正的读数据,写数据,还包括接收连接accept(),发起连接connect()等操作…

非阻塞IO:当你去读写一个非阻塞的文件描述符时,不管可不可以读写,它都会立即返回,返回成功说明读写操作完成了,返回失败会设置相应errno状态码,根据这个errno可以进一步执行其他处理。它不会像阻塞IO那样,卡在那里不动!!!


select()/poll()模型都是水平触发模式信号驱动I/O是边缘触发模式epoll()模型既支持水平触发,也支持边缘触发,默认是水平触发


别人的一些总结:

  1. 对于监听的sockfd,最好使用水平触发模式,边缘触发模式会导致高并发情况下,有的客户端会连接不上。如果非要使用边缘触发,网上有的方案是用while来循环accept()。
  2. 对于读写的connfd,水平触发模式下,阻塞和非阻塞效果都一样,不过为了防止特殊情况,还是建议设置非阻塞。
  3. 对于读写的connfd,边缘触发模式下,必须使用非阻塞IO,并要一次性全部读写完数据。

在LT(水平触发)模式下,只要这个fd还有数据可读,每次 epoll_wait 都会返回它的事件,提醒用户程序去操作,而在ET(边缘触发)模式中,它只会提示一次,直到下次再有数据流入之前都不会有提示了,无论fd中是否还有数据可读。所以在ET模式下,读/写一个fd的时候一定要把它的buffer读/写光,也就是说一直读/写到read/write的返回值小于请求值,或者遇到EAGAIN错误。

参考链接:

实例浅析epoll的水平触发和边缘触发,以及边缘触发为什么要使用非阻塞IO #代码+实例
http://www.cnblogs.com/yuuyuu/p/5103744.html

自己趟过epoll的坑
http://youbingchenyoubing.leanote.com/post/%E8%87%AA%E5%B7%B1%E8%B6%9F%E8%BF%87epoll%E7%9A%84%E5%9D%91

Linux IO模式及 select、poll、epoll详解
https://segmentfault.com/a/1190000003063859

epoll的ET和LT触发方式
https://jeff-linux.gitbooks.io/muduo-/chapter2.html

epoll模型ET和LT
http://www.firefoxbug.com/index.php/archives/1942/

Epoll的 水平触发和边缘触发
http://www.cleey.com/blog/single/id/791.html

=END=

声明: 除非注明,ixyzero.com文章均为原创,转载请以链接形式标明本文地址,谢谢!
https://ixyzero.com/blog/archives/3515.html

《Linux下epoll的边缘出发、水平触发》上有5条评论

  1. 怎样理解阻塞非阻塞与同步异步的区别?
    https://www.zhihu.com/question/19732473/answer/20851256

    在处理 IO 的时候,阻塞和非阻塞都是同步 IO。
    只有使用了特殊的 API 才是异步 IO。

    1.同步与异步同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)
    所谓同步,就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由*调用者*主动等待这个*调用*的结果。
    而异步则是相反,*调用*在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。

    2. 阻塞与非阻塞
    阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。

    阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
    非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

  2. 【高并发编程】再谈同步、异步、阻塞、非阻塞
    http://blog.csdn.net/xxxxxx91116/article/details/51233785

    小张喜欢喝咖啡,同时养了好多狗;

    出场:
    1. 小张:相当于我们的客户端进程
    2. 小狗大黑:阻塞处理的IO函数
    3. 小狗大黄:非阻塞处理的IO函数
    4. 小狗大白、大红:异步处理的IO函数

    同步阻塞:
    小张派大黑去看咖啡煮好没,大黑等咖啡煮开了才回来;

    同步非阻塞:
    小张派大黄去看咖啡煮好没,大黄看了一眼就回来了,过了一会,再大黄再去看看咖啡煮好没;

    异步非阻塞:
    小张派大白和大红去看咖啡煮好没,大白和大红到了厨房后,大白就回来告诉小张,大红已经到厨房啦;过了一会咖啡煮好了,大红回到客厅告诉小张;

    异步阻塞:(这个太傻了,目前还没遇到)
    小张派大白和大红去看咖啡煮好没,大白和大红到了厨房后,一起在那等着;过了一会咖啡煮好了,大红大白一起回到客厅告诉小张;

    那么采用何种方式,要看小张有没有养这个类型的狗(系统有没有相关API),在有的情况下,就看小张个人的需求了(业务需求)

  3. 聊聊同步、异步、阻塞与非阻塞
    https://www.jianshu.com/p/aed6067eeac9

    同步/异步关注的是消息通知的机制,而阻塞/非阻塞关注的是程序(线程)等待消息通知时的状态。

    以小明下载文件打个比方,从这两个关注点来再次说明这两组概念,希望能够更好的促进大家的理解。

    同步阻塞:小明一直盯着下载进度条,到 100% 的时候就完成。
    同步非阻塞:小明提交下载任务后就去干别的,每过一段时间就去瞄一眼进度条,看到 100% 就完成。

    异步阻塞:小明换了个有下载完成通知功能的软件,下载完成就“叮”一声。不过小明仍然一直等待“叮”的声音(看起来很傻,不是吗)。
    异步非阻塞:仍然是那个会“叮”一声的下载软件,小明提交下载任务后就去干别的,听到“叮”的一声就知道完成了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注