epoll的实现原理(2)

epoll的实现原理(2)参考自:The Implementation of epoll(3)The Implementation of epoll(4)回调函数 ep_poll_callback()前面提到的ep_insert()函数将epoll实例附加到监视文件描述符fd的等待队列,注册ep_poll_callback()为队列唤醒的回调函数。下面剖析一下这个回调函数:static...
摘要由CSDN通过智能技术生成

epoll的实现原理(2)

笔记,内容翻译自:

The Implementation of epoll(3)

The Implementation of epoll(4)

回调函数 ep_poll_callback()

前面提到的ep_insert()函数将epoll实例附加到监视文件描述符fd的等待队列,注册ep_poll_callback()为队列唤醒的回调函数。下面剖析一下这个回调函数:

static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key)
{
                              //↑ pwq->wait
	int pwake = 0;
	unsigned long flags;
	struct epitem *epi = ep_item_from_wait(wait);  //通过strcut eppoll_entry找到epitem
	struct eventpoll *ep = epi->ep;                //进一步找到eventpoll

接下来,使用自旋锁锁定eventpoll

spin_lock_irqsave(&ep->lock, flags);

**然后检查事件是否是用户让epoll监视的。**前面ep_insert()将注册事件为~0,有两个原因:

1.用户可能频繁改变需要监视的事件,但是重新注册poll回调效率不高。

2.其次,并非所有的事件都遵循系统的事件掩码设置,因此完全依靠系统的设置不太可靠。

if (key && !((unsigned long) key & epi->event.events))
	goto out_unlock;

如果没有监控任何事件,跳到解锁out_unlock

接下来检查epoll实例是否正尝试将事件传输到用户态(也就是在调用ep_send_events_proc()时)。

如果是的话,将当前epitem加入到一个链表头在 struct eventpoll中的单链表里。代码如下:

if (unlikely(ep->ovflist != EP_UNACTIVE_PTR)) {
    //正在传输为NULL(默认状态是EP_UNACTIVE_PTR)
	if (epi->next == EP_UNACTIVE_PTR) {
   				
		epi->next = ep->ovflist;                 //前面已经取得了ep的锁
		ep->ovflist = epi;
		if (epi->ws) {
   
			__pm_stay_awake(ep->ws);
		}
	}
	goto out_unlock;                              //完成后跳到解锁
}

不是的话,接下来ep_poll_callback() 检查当前的struct epitem 是否已经在就绪队列中。

在用户没有没有机会调用epoll_wait()时可能发生这种情况(以前加入过了,用户还没机会处理)。

如果不在的话,函数会将struct epitem 加入到就绪队列(struct eventpoll的成员rdllist )中。

if (!ep_is_linked(&epi->rdllink)) {
   
	list_add_tail(&epi->rdllink, &ep->rdllist);
	ep_pm_stay_awake_rcu(epi);
}

然后 ep_poll_callback()唤醒等待wqpoll_wait的进程。

wq用于在超时时间(timeout)没到时,用户正在通过epoll_wait()等待events的时候(最多唤醒一个进程)。

poll_wait是epoll实现的文件系统的poll(),请记住epoll同样是一个可轮询的文件描述符。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值