I/O多路复用之总结
2015-08-08 23:55
281 查看
poll() 和 select() 的区别
虽然 poll() 和select() 完成相同的工作,但 poll() 调用在很多方面仍然优于 select() 调用:poll() 不需要用户计算最大文件描述符值加 1 作为参数传递给它。
poll() 对于值最大的文件描述符,效率最高。试想一下,要通过 select() 监视一个值为900的文件描述符,内核需要检查每个集合中的每个位,一直检查900个位。
select() 的文件描述符集合是静态的,需要对大小设置进行权衡:如果值很小,会限制 select() 可监视的最大文件描述符值;如果值很大,效率会很低。当值很大时,大的位掩码操作效率不高,尤其是当无法确定集合是否稀疏集合。对于 poll(),可以准备创建大小合适的数组。如果只需要监视一项,则仅传递一个结构体。
对于 select() 调用,返回时会重新创建文件描述符集,因此每次调用都必须重新初始化。poll() 系统调用会把输入(events变量)和输出(revents变量) 分离开,支持无需改变数组就可以重新使用。
select() 的调用的 timeout 参数在返回时是未定义的。代码要支持可移植,需要重新对它初始化。而对于 pselect(),不存在这些问题。
不过,select() 系统调用也有些优点:
select() 可移植更好,因为有些UNIX系统不支持 poll()。
select() 提供了更高的超时精度:select() 支持微秒级,poll() 支持毫秒级。ppoll() 和 pselect() 理论上都提供了纳秒级的超时精度,但是实际上,这两个调用的毫秒级精度都不可靠。
比起 poll() 调用和 select() 调用,epoll() 调用更优,epoll() 是Linux特有的I/O多路复用解决方案。
边缘触发事件和条件触发事件
select() 操作和 poll() 操作都是条件触发(level-triggered),而不是边缘触发(edge-triggered)。epoll() 两种模式都支持。边缘触发更简单,但是不注意的话很容易丢失 I/O 事件。注:条件触发是指当条件满足时发生一个 I/O 事件,边缘触发是指当状态改变时发生一个 I/O 事件。
如果 epoll_ctl() 的参数 event 中的 events 项设置为 EPOLLET, fd 上的监听方式为边缘触发(Edge-triggered),否则为条件触发(Level—triggered)。
考虑下面的生产者和消费者在通过UNIX管道通信时的情况。
1. 生产者向管道写入1KB数据。
2.消费者在管道上调用 epoll_wait(),等待管道上有数据并可读。
通过条件触发监视时,在步骤2中 epoll_wait() 调用会立即返回,表示管道可读。通过边缘触发监视时,需要步骤1发生后,步骤2的 epoll_wait() 调用才会返回。也就是说,对于边缘触发,在调用 epoll_wait() 时,即使管道已经可读,也只有当数据写入之后,调用才会返回。
条件触发是默认行为,poll() 和 select() 就是采用这种模式,也是大多数开发者所期望的。边缘触发需要不同的编程方案,通常是使用非阻塞 I/O,而且需要仔细检查 EAGAIN。
边缘触发
“边缘触发”这个术语来源于电子工程领域。条件触发是只要有状态发生就触发。边缘触发是只有在状态改变的时候才会发生。条件触发关心的是事件状态,边缘触发关心的是事件本身。
举个例子,对于一个读操作的文件描述符,如果是条件触发,只要文件描述符可读了,就会收到通知,是“可读”这个条件触发了通知。如果是边缘触发,当数据可读时,会接收到通知,而且通知有且仅有一次:是“有数据”这个变化本身触发了通知。
相关文章推荐
- java并发(一) CountDownLatch (在多个线程都结束后再去执行某个任务)
- 值类型 和引用类型以及
- mysql文档摘要续
- 【LeetCode】14 - Longest Common Prefix
- django book学习笔记――高级视图和URL配置
- Java基础——GUI概述
- 《深入浅出struts2》--第23章,自定义插件
- oracle解除锁表
- Microsoft SQL Server 2008 基本安装说明
- shell sed
- Python-Selenium2做Web自动化测试(1)-软件测试分类以及什么时候需要进行自动化测试
- hdu 3480 dp 四边形不等式优化
- hdu1242(Rescue)
- linux socket 编程一:简单的服务器和客户端通信
- ognl表达式的部分功能
- ANSI C, Variable Length Array, Dynamic Memory Allocation, Memory Reservation and Late Binding
- git命令
- iOS开发网络篇—NSURLConnection基本使用(二)
- 01_01 JSP基础语法之Scriptlet
- Bash的命令替换