Pride's Blog

epoll机制

· Pride

epoll是Linux核心的可扩展I/O事件通知机制[1]。于Linux 2.5.44首度登场,它设计目的旨在取代既有POSIX select(2)与poll(2)系统函式,让需要大量操作档案描述子的程式得以发挥更优异的效能(举例来说:旧有的系统函式所花费的时间复杂度为O(n),epoll的时间复杂度O(log n))。epoll 实现的功能与poll 类似,都是监听多个档案描述子上的事件。

epoll与FreeBSD的kqueue类似,底层都是由可组态的作业系统核心物件建构而成,并以档案描述子(file descriptor)的形式呈现于使用者空间。epoll通过使用红黑树(RB-tree)搜寻被监视的档案描述子(file descriptor)。

在epoll 实例上注册事件时,epoll 会将该事件添加到epoll 实例的红黑树上并注册一个回呼函式,当事件发生时会将事件添加到就绪连结串列中。

在聊epoll机制之前,需要从一些概念和select/poll机制聊起,再切如到epoll中,以及epoll与其两者的区别。

一、概念须知§

1.进程切换§

进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,其具备挂起暂停执行与恢复继续执行的能力,操作系统的内核通过进程切换来挂起或恢复进程状态。

2.文件描述符Fd§

Linux / Unix系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符,文件描述符就是内核为了高效管理已被打开的文件所创建的索引,用来指向被打开的文件,所有执行I/O操作的系统调用都会通过文件描述符。

3.缓存 I/O§

缓存I/O又被称作标准I/O,大多数文件系统的默认I/O操作都是缓存I/O。在 Linux 的缓存 I/O 机制中,操作系统会将 I/O 的数据缓存在文件系统的页缓存(page cache)中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。

二、I/O模型§

IO (Input/Output,输入/输出)即数据的读取(接收)或写入(发送)操作,通常用户进程中的一个完整IO分为两阶段:

三、I/O多路复用§

Linux操作系统中存在select、poll、epoll三种多路复用机制,I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作,其本质上都是同步I/O。

1.select()§

/*
 * maxfdp1      最大 fd 数值 +1,大于此数值的 fd 会被忽略
 * readset      读变化监视 fd 集合,可为 NULL
 * writeset     写变化监视 fd 集合,可为 NULL
 * exceptset	错误异常变化监视 fd 集合,可为 NULL
 * timeout      超时时间,NULL:阻塞,0:非阻塞,>0:等待
 */
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
           const struct timeval *timeout);