我们提供安全,免费的手游软件下载!
边缘模式(ET)与水平模式(LT)是epoll事件分发接口的两种模式。ET模式下,内核只会上报一次同一事件,如果代码没有读取完所有可读取的数据,继续调用epoll_wait则不会收到事件。通常要将ET模式设定为非阻塞模式,并等到读取数据返回EAGAIN或者。
相比之下,LT模式下调用epoll_wait后会继续有事件触发。LT模式与poll保持相同的语义,但性能比poll更好。
对于流式连接(如pipe、fifo、tcp等),可以通过判断read的返回值是否小于指定读取的大小来判断缓冲区中的数据是否已经读完。而对于数据报(如udp等),通常需要持续读取到EAGAIN返回,才能判断缓冲区数据已经读完。每次从epoll_wait返回后都需要调用epoll_ctl往epoll中继续增加事件。
EPOLLEXCLUSIVE标志可以解决多个fd指向同一个文件时可能产生的惊群问题。加了这个标志后,至少一个fd能收到事件。
在ET模式下,某个文件可能会不停地进行read,导致其他fd一直等待,造成饥饿现象。为避免epoll的饥饿模式,可以将可读的fd放到一个list里面,然后对这个list中的fd分别执行read,并通过限制每个fd一次read的字节数来控制切换到其他fd,当一个fd读完后从list删除掉。
在/proc/sys/fs/epoll/max_user_watches中记录了系统范围内限制加入到epoll中的句柄数,实际上是限制句柄相关的内存最多只能占用内存的4%。
epoll_wait的实现过程包括用户调用epoll_wait,系统调用统一入口根据系统调用号走到内核对应的sys_epoll_wait处理函数,然后判断epoolfd里面关联的文件句柄是否有可读的句柄。如果暂时没有,epoll_wait线程会等待在这些句柄的queue上。一旦这些文件句柄有数据进来后,内核的ksoftirqd线程会尝试唤醒线程,并从上次线程切换的位置重新执行sys_epoll_wait。
参考资料:
热门资讯