水平触发和边缘触发

水平触发

绪通知方式是水平触发,也就说如果内核通知应用层某一个文件描述符已经就绪,而如果应用层此后一直没有完整的处理该描述符(没有读取完相应的数据或者没有写入任何数据),那么内核会不断地通知应用层该文件描述符已经就绪。这就是所谓的水平触发:只要条件满足,那内核就会触发一个事件(只要文件描述符对应的数据没有被读取或者写入,那内核就不断地通知你)。

  边缘触发

所谓边沿触发是相对水平触发而言的,也就是说内核只是在文件描述符的状态发生变换的时候才进行通知。这就意味着在大多数情况下,当内核通知某个读描述符就绪后,除非该读描述符内部缓冲区的所有数据已经完全被读取从而使得就绪状态发生了变化,否则内核不会发出任何新的通知,会永远沉默下去。如果该文件描述符的receive操作返回EWOULDBLOCK错误码,这就意味着该描述符的就绪状态已经被打破,你需要等待下一次的边沿触发通知

除了上面所说的问题,一旦使用了边沿触发,另外一个随之而来的问题就是,你需要注意一个常见的“意外事件”的问题。因为os实现边沿触发的一个常见的实现bug就是在某些情况下内核一旦收到新数据包就会通知就绪,不管你上一次的就绪通知是否被用户处理。因此你必须小心组织你的代码,你需要处理好每一个就绪通知,如果某一次就绪通知的数据没有被正确得完整得处理你就急急忙忙得开始等待下一次通知,那么下一次的就绪通知就会覆盖掉前面的数据,那么你就会永远不会恢复了。

相比之下,这种方式对于程序员编码的要求可能会更高一些,一旦应用程序错过了一次通知,那么与之对应的客户端就永远崩溃了(意外事件)或者沉默(没有读取完上一次事件产生的数据)。而方式1则会不断提醒用户缓冲区内还有数据。因此,对于边沿触发方式的就绪通知,应用层必须在每次就绪通知后读取数据,一直读到EWOULDBLOCK为止。

这种方式在Linux中主要通过epoll实现。实际上java nio采用的也是这种IO策略。Epollpoll有一些共同之处,epoll在默认情况下也是水平触发的,此时你可以认为epoll是一个增强版的poll,它的效率更高,这是因为epoll采用了一些优化,比如只关心活跃的连接,通过共享内存空间避免了内存拷贝等等。

来自http://www.360doc.com/content/13/0522/18/1542811_287328391.shtml

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值