epoll機制代碼覈對

epoll工作機理

       epoll_wait檢查epoll句柄中的rdllist不爲空退出循環

       遍歷所有的epitem,把各種ready的fd收集起來返回

誰來影響rdllist不爲空,一般的說法是文件的fd的狀態發生改變,就能有某個方法將fd加入到rdllist中,並通知調用epoll_wait的進程

        在epoll_add的時候,會註冊回調函數,在fd準備好的時候,執行這個回調函數更新rdllist

那麼這個過程是怎麼樣的呢?

       ep_poll_callback會完成rdllist的狀態更新

回調函數的調用鏈

       tcp_v4_do_rcv(net/ipv4/tcp_ipv4.c)

       tcp_rcv_established(net/ipv4/tcp_input.c)

       sock_def_readable(net/core/sock.c)

       wake_up_interruptiable_sync_poll(wait.h)

       __wake_up_sync_key(kernel/sched.c)

       __wake_up_common(kernel/sched.c)

   static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,int nr_exclusive, int wake_flags, void *key)
      {
                 wait_queue_t *curr, *next;
                list_for_each_entry_safe(curr, next, &q->task_list, task_list) 
               {
                   unsigned flags = curr->flags;
                   if (curr->func(curr, mode, wake_flags, key) && 
                        (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
                    break;
              }
      }

      func就是ep_poll_callback,從而完成了rdllist中的變更

回調函數是如何註冊進去的呢?

      ep_insert=>sock_poll=>sock->ops->poll(tcp_poll)=>sock_poll_wait-=>poll_wait=>ep_ptable_queue_proc-=>init_waitqueue_func_entry

   ep_insert(struct eventpoll *ep, struct epoll_event *event,struct file *tfile, int fd)
   {  
     ....
     revents = tfile->f_op->poll(tfile, &epq.pt);
     ....
   }
   static const struct file_operations socket_file_ops = {
        .owner =THIS_MODULE,
        .poll =sock_poll,
   };
   
   static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
   {
            if (p && wait_address)
            p->qproc(filp, wait_address, p);
                //qproc就是ep_ptable_queue_proc
  }
   static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,poll_table *pt)
  {
        ......
        init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
        .....
   }
   static inline void init_waitqueue_func_entry(wait_queue_t *q,wait_queue_func_t func)
   {
      q->flags = 0;
      q->private = NULL;
      q->func = func; //ep_poll_callback
   }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章