内核源码IO多路复用EPOLL

1. 简介:

        本文将介绍内核epoll实现的原理。基于kernel 2.6.32版本。

        本文只描述epoll对其他fd的监听,由于epoll本身也是一种文件系统,也可以被监听,这一部分不在这里介绍。

2. 基础数据结构:

        epoll中主要数据结构有两个,一个是epoll_create创建的epoll_fd的结构体eventpoll,一个是事件源对应的epitem结构体。

        epollevent的数据结构及相应解释如下:这里注意的是eventpoll中其实有两个ready list,一个是常规的rdllist,还有一个是ovflist,两个队列的区别是ovflist用于当前epoll已经在将ready list发送到用户空间时,这时候设备状态改变唤醒的时候不能直接添加在ready list中,而是需要添加在ovflist,当ready list处理完时候再从ovflist移到ready list,相当于一个备用的队列。

struct eventpoll {
	/* Protect the this structure access */
	spinlock_t lock;

	/*
	 * This mutex is used to ensure that files are not removed
	 * while epoll is using them. This is held during the event
	 * collection loop, the file cleanup path, the epoll file exit
	 * code and the ctl operations.
	 */
	struct mutex mtx;

	/* Wait queue used by sys_epoll_wait() */
	/* 用于epoll_wait时等待事件激活时让出本进程调度权限时候的等待队列。  */
	wait_queue_head_t wq;

	/* Wait queue used by file->poll() */
	/* 用于epoll这个文件类型的对应的poll操作。  */
	wait_queue_head_t poll_wait;

	/* List of ready file descriptors */
	/* 已激活的事件队列。  */
	struct list_head rdllist;

	/* RB tree root used to store monitored fd structs */
	/* 管理所有事件源,用于epoll_ctl中查找epitem。  */
	struct rb_root rbr;

	/*
	 * This is a single linked list that chains all the "struct epitem" that
	 * happened while transfering ready events to userspace w/out
	 * holding ->lock.
	 */
	/* 用于当epoll准备将数据返回给用户时候(ep_send_events_proc),
	 * 这时候设备状态改变回调(ep_poll_callback)的时候,
	 * 不直接添加在ready list中,而是先暂时放在ovflist,
	 * 当ep_send_events_proc结束的时候,重新把ovflist中的数据加到ready list中。  */
	struct epitem *ovflist;

	/* The user that created the eventpoll descriptor */
	/* 主要用来统计当前监听多少个fd。  */
	struct user_struct *user;

	/* epfd对应的struct file。  */
	struct file *file;

	/* used to optimize loop detection check */
	/* 用于把一个epfd添加到另一个epoll中监听时候检测用。  */
	int visited;
	struct list_head visited_list_link;
};
        epitem结构体及相应解释如下:

struct epitem {
	/* RB tree node used to link this structure to the eventpoll RB tree */
	/* 记录在struct eventpoll中的rbr节点。  */
	struct rb_node rbn;

	/* List header used to link this structure to the eventpoll ready list */
	/* 记录在struct eventpoll中的rdllist节点。  */
	struct list_head rdllink;

	/*
	 * Works together "struct eventpoll"->ovflist in keeping the
	 * single linked chain of items.
	 */
	/* 记录在struct eventpoll中的ovflist节点,ovflist用处见eventpoll。  */
	struct epitem *next;

	/* The file descriptor information this item refers to */
	/* 文件描述符和对应的file结构体的封装
	 * struct epoll_filefd {
	 * struct file *file;
	 * int fd;
	 * };
	 */
	struct epoll_filefd ffd;

	/* Number of active wait queue attached to poll operations */
	int nwait;

	/* List containing poll wait queues */
	/* 
	 * struct eppoll_entry {
	 * /* List header used to link this structure to the "struct epitem" */
	 * struct list_head llink;

	 * /* The "base" pointer is set to the container "struct epitem" */
	 * struct epitem *base;

	 * /*
	 *  * Wait queue item that will be linked to the target file wait
	 *  * queue head.
	 *  */
	 * wait_queue_t wait;

	 * /* The wait queue head that linked the "wait" wait queue item */
	 * wait_queue_head_t *whead;
	 * };
	 * struct eppoll_entry节点,该节点在每个事件源在相应的设备中注册(ep_ptable_queue_proc)时候创建,
	 * 结构体中主要封装了当前事件源对应epitem,事件源在相应设备系统中的钩子和队列
	 * 当设备状态改变回调时,将通过eppoll_entry中的wait找到eppoll_entry结构体再
	 * 找到epitem(ep_item_from_wait)
	 */
	struct list_head pwqlist;

	/* The "container" of this item */
	/* 记录epitem所在的eventpoll。  */
	struct eventpoll *ep;

	/* List header used to link this item to the "struct file" items list */
	/* struct file中的f_ep_links节点,好像是用作递归深度的检测,暂时没懂。  */
	struct list_head fllink;

	/* The structure that describe the interested events and the source fd */
	/* 用户监听的事件类型。  */
	struct epoll_event event;
};

3. EPOLL简单的运作流程:

        epoll简单流程和reactor模式有一些相似,通过epoll来对事件源(用户关注的某个设备的某个状态)进行管理,每添加一个事件源,都会在对应设备上进行注册。当事件源有用户所关注的事件触发,就在中断回调时加入到epoll的ready list中,当用户epoll_wait的时候,等待超时时间(无事件触发),交出调度权,进程唤醒后如果有事件就将事件通知给用户,简单示意图如下:当然内在还有其他更多的细节处理,下文会描述。

4. epoll源码:

4.1 epoll_create ():

        epoll_create将创建一个属于epoll文件系统的file,同时创建一个eventpoll的结构体,作为file的private_data,这里只注意eventpoll结构体初始化的函数ep_alloc中的ovflist,当其初始化为EP_UNACTIVE_PTR时,表示不使用该队列,当该队列开放使用时

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值