Linux内核epoll ET/LT辨析

本文基于linux 3.10.104 x86_64内核,接上篇针对epoll ET和LT不同模式下的事件处理进行分析,对应源码位于fs/eventpoll.c。


static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
			       void *priv)
	struct ep_send_events_data *esed = priv;
	int eventcnt;
	unsigned int revents;
	struct epitem *epi;
	struct epoll_event __user *uevent;
	struct wakeup_source *ws;
	poll_table pt;

	init_poll_funcptr(&pt, NULL);

	 * We can loop without lock because we are passed a task private list.
	 * Items cannot vanish during the loop because ep_scan_ready_list() is
	 * holding "mtx" during this call.
	for (eventcnt = 0, uevent = esed->events;
	     !list_empty(head) && eventcnt < esed->maxevents;) {
		epi = list_first_entry(head, struct epitem, rdllink);

		 * Activate ep->ws before deactivating epi->ws to prevent
		 * triggering auto-suspend here (in case we reactive epi->ws
		 * below).
		 * This could be rearranged to delay the deactivation of epi->ws
		 * instead, but then epi->ws would temporarily be out of sync
		 * with ep_is_linked().
		ws = ep_wakeup_source(epi);
		if (ws) {
			if (ws->active)


		revents = ep_item_poll(epi, &pt);

		 * If the event mask intersect the caller-requested one,
		 * deliver the event to userspace. Again, ep_scan_ready_list()
		 * is holding "mtx", so no operations coming from userspace
		 * can change the item.
		if (revents) {
			if (__put_user(revents, &uevent->events) ||
			    __put_user(epi->, &uevent->data)) {
				list_add(&epi->rdllink, head);
				return eventcnt ? eventcnt : -EFAULT;
			if (epi-> & EPOLLONESHOT)
				epi-> &= EP_PRIVATE_BITS;
			else if (!(epi-> & EPOLLET)) {
				 * If this file has been added with Level
				 * Trigger mode, we need to insert back inside
				 * the ready list, so that the next call to
				 * epoll_wait() will check again the events
				 * availability. At this point, no one can insert
				 * into ep->rdllist besides us. The epoll_ctl()
				 * callers are locked out by
				 * ep_scan_ready_list() holding "mtx" and the
				 * poll callback will queue them in ep->ovflist.
				list_add_tail(&epi->rdllink, &ep->rdllist);

	return eventcnt;




您的电子邮箱地址不会被公开。 必填项已用 * 标注