epoll源码剖析

asmlinkage long sys_epoll_create(int size)

功能概要:
1、在执行sys_epoll_create之前会有个初始化工作,它挂在了一个文件系统“eventpollfs”,然后create就是在这个文件系统下分配一个fd给用户
该函数构造相应的数据结构,file,inode,以及分配fd
2、开辟一个eventpoll结构,并且将fd对应的file->private_data指向它
eventpoll结构体定义:
struct eventpoll {
	/* Protect the this structure access */
	rwlock_t lock;

	/*
	 * This semaphore is used to ensure that files are not removed
	 * while epoll is using them. This is read-held during the event
	 * collection loop and it is write-held during the file cleanup
	 * path, the epoll file exit code and the ctl operations.
	 */
	struct rw_semaphore sem;

	/* Wait queue used by sys_epoll_wait() */
	wait_queue_head_t wq;

	/* Wait queue used by file->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 */
	struct rb_root rbr;
};
这个结构里面有就绪fd对应的epitem链表,这个结构的等待队列(所有调用epoll_wait的进程的等待队列),用于所有fd对应的epitem对应的连接的红黑树的根

asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)

功能概要:
1、将根据epfd获取到创建时的eventpoll结构,然后在此结构中红黑树种查找这个fd对应的节点是否存在,存在又是插入操作就直接返回,否则根据op选择相应的函数,如果为ADD就调用ep_insert()
2、当然还有将用户空间的传进来的事件拷贝进内核(第一次不可避免,以后就不需要重复传递)

static int ep_insert(struct eventpoll *ep, struct epoll_event *event, struct file *tfile, int fd)

功能概要:
1、申请一个epitem结构,根据fd,events组装一个epitem插入红黑树中
struct epitem {
	/* RB-Tree node used to link this structure to the eventpoll rb-tree */
	struct rb_node rbn;

	/* List header used to link this structure to the eventpoll ready list */
	struct list_head rdllink;

	/* The file descriptor information this item refers to */
	struct epoll_filefd ffd;

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

	/* List containing poll wait queues */
	struct list_head pwqlist;

	/* The "container" of this item */
	struct eventpoll *ep;

	/* The structure that describe the interested events and the source fd */
	struct epoll_event event;

	/*
	 * Used to keep track of the usage count of the structure. This avoids
	 * that the structure will desappear from underneath our processing.
	 */
	atomic_t usecnt;

	/* List header used to link this item to the "struct file" items list */
	struct list_head fllink;

	/* List header used to link the item to the transfer list */
	struct list_head txlink;

	/*
	 * This is used during the collection/transfer of events to userspace
	 * to pin items empty events set.
	 */
	unsigned int revents;
};


2、开辟一个ep_pqueue这样一个队列节点,其中的函数指针指向ep_ptable_queue_proc
struct ep_pqueue {
	poll_table pt;
	struct epitem *epi;
};

3、调用该文件描述符的poll方法,这里第一次仅仅将该进程加入该文件描述符的等待队列中

static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,poll_table *pt)

功能概要:
申请一个ep_pentry结构体:
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" */
	void *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;
};
1、这里将base指向epitem,将wait中的的唤醒函数设置为ep_poll_callback,task设置为本进程的PCB,whead设置为该文件的等待队列的头,然后将wait把当前进程通过whead挂入该文件的等该队列,这里加入队列之后就不需要再次调用加入,以后就是通过epoll_wait等待就对了
2、当哪个文件的有事件到达时就调用ep_poll_callback函数,此函数的功能就是将就绪的epitem加入eventpoll中的就绪队列中

asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,    int maxevents, int timeout)

功能概要:
1、扫描rdlist队列中是否为空,为空就睡眠,不为空就从相应的epitem中中file调用poll方法得到掩码复制给revents,并将revents拷贝到用户空间events中,events是一个epoll_event结构体数组指针,将发生事件的所有的fd,相应事件都保存在其中。
2、将epitem从rdlist中通过txlink链接到一个txlist中(传输链表中),比对传输链接中的每一个epitem是否为EPOLLET模式,不是ET模式就将epitem放回rdlist中,否则就从链表中删除

优点:

1、没有最大文件描述符的限制
2、只有第一次才会从用户空间进行拷贝,后面调用不需要重复拷贝,返回结果也是只返回有事件发生的fd,其他不返回,提高了效率
3、只会把该进程往文件的等待队列中加一次

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值