IO
IO多路复用
BIO
NIO
select
poll
epoll
水平触发和边沿触发
-
水平触发只关心文件描述符中是否还有没完成处理的数据,如果有,不管怎样
epoll_wait
,总是会被返回。简单说——水平触发代表了一种“状态”。 -
边沿触发只关心文件描述符是否有新的事件产生,如果有,则返回;如果返回过一次,不管程序是否处理了,只要没有新的事件产生,
epoll_wait
不会再认为这个fd被“触发”了。简单说——边沿触发代表了一个“事件”。“
那么边沿触发怎么才能迫使新事件产生呢?一般需要反复调用
read
/write
这样的IO接口,直到得到了EAGAIN
错误码,再去尝试epoll_wait
才有可能得到下次事件。
那么为什么需要边沿触发呢?
边沿触发把如何处理数据的控制权完全交给了开发者,提供了巨大的灵活性。比如,读取一个http的请求,开发者可以决定只读取http中的headers数据就停下来,然后根据业务逻辑判断是否要继续读(比如需要调用另外一个服务来决定是否继续读)。而不是次次被socket尚有数据的状态烦扰;写入数据时也是如此。比如希望将一个资源A写入到socket。当socket的buffer充足时,epoll_wait
会返回这个fd是准备好的。但是资源A此时不一定准备好。如果使用水平触发,每次经过epoll_wait
也总会被打扰。在边沿触发下,开发者有机会更精细的定制这里的控制逻辑。
但不好的一面时,边沿触发也大大的提高了编程的难度。一不留神,可能就会miss掉处理部分socket数据的机会。如果没有很好的根据EAGAIN
来“重置”一个fd,就会造成此fd永远没有新事件产生,进而导致饿死相关的处理代码。