poll系統調用的核心態實現機制分析

來源:互聯網
上載者:User

著作權,轉載請標明出處   All right reserved,Copyright by 徐行而至 淺唱而歸

前面已經比較詳盡的分析了系統調用引發的核心執行過程,本文將繼續分析一下linux2.6.38核心源碼中poll函數(與select實作類別似,兩者本質相同,因為其實現機制相同,並且最終都將調用驅動中層的poll函數)的實現。

通過前面的分析,我們知道,應用程式中的open、read、write函數系統調用都會觸發非強制中斷異常,從而進入異常處理,在異常處理中將會擷取使用者態傳入的系統調用號,根據系統調用號在系統調用表中索引出實際的系統調用處理函數,如核心裡的sys_open、sys_read、sys_write函數,而核心裡的這些函數又會對應到驅動程式裡的open、read、write函數。

poll機制也不例外,使用者空間裡調用poll函數或者select函數時,都會調用到核心空間的sys_poll或者sys_select函數。下面以sys_poll來分析使用者空間poll的實現:

使用者空間調用:poll核心: asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,long timeout);即SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,long, timeout_msecs)         //以前分析過,實際為宏

其實現如下:

\fs\select.c

SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,long, timeout_msecs){struct timespec end_time, *to = NULL;int ret;if (timeout_msecs >= 0) {to = &end_time;poll_select_set_timeout(to, timeout_msecs / MSEC_PER_SEC,NSEC_PER_MSEC * (timeout_msecs % MSEC_PER_SEC));}ret = do_sys_poll(ufds, nfds, to);if (ret == -EINTR) {struct restart_block *restart_block;restart_block = ¤t_thread_info()->restart_block;restart_block->fn = do_restart_poll;restart_block->poll.ufds = ufds;restart_block->poll.nfds = nfds;if (timeout_msecs >= 0) {restart_block->poll.tv_sec = end_time.tv_sec;restart_block->poll.tv_nsec = end_time.tv_nsec;restart_block->poll.has_timeout = 1;} elserestart_block->poll.has_timeout = 0;ret = -ERESTART_RESTARTBLOCK;}return ret;}

為了使結構簡要直觀,我們只列出調用關係架構:

使用者空間:poll核心: asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,long timeout);即SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,long, timeout_msecs)         //以前分析過,實際為宏poll_select_set_timeout(to, timeout_msecs / MSEC_PER_SEC,NSEC_PER_MSEC * (timeout_msecs % MSEC_PER_SEC));//配置逾時時間do_sys_poll(ufds, nfds, to);poll_initwait(&table);//初始化等待隊列init_poll_funcptr(&pwq->pt, __pollwait);pt->qproc = qproc; /*table->pt->qproc= __pollwait;詳見注釋1-2*/do_poll(nfds, head, &table, end_time);for (;;){for (; pfd != pfd_end; pfd++)//針對多個進程{if (do_pollfd(pfd, pt))        /*do_pollfd會調用驅動poll函數,poll裡面的poll_wait最終調用pt->qproc函數(即__pollwait)將進程中可能引起待監測內容狀態變化的等待隊列鏈表頭掛載到查詢表中,除此以外,poll還會根據條件判斷事件是否發生,發生則將mask設定為非零的掩碼,並返回該值,詳見注釋1-1*/{count++;       //驅動中的poll函數返回非零的掩碼則自加,記錄等待事件發生的進程數 pt = NULL;   }}if (!count)   /*若count為0(表示無等待的事件發生)*/{count = wait->error;if (signal_pending(current))     /*判斷是否為訊號喚醒*/count = -EINTR;}/*若count不為0(有等待的事件發生了)或者timed_out不為0(有訊號發生或逾時),則推出休眠*/ if (count || timed_out)                                                               break ;/*上述條件不滿足時進入休眠,若有等待的事件發生了,逾時或收到訊號則喚醒*/if (!poll_schedule_timeout(wait, TASK_INTERRUPTIBLE, to, slack))timed_out = 1;}poll_freewait(&table); //清除poll_wqueues佔用的資源,包括加入到查詢表中的等待隊列鏈表頭

注釋1-1:

do_pollfd(pfd, pt)

mask = file->f_op->poll(file, pwait);/*調用驅動程式中的poll函數,若poll驅動函數傳回值不為0,則事件發生,則會使count++*/

調用關係如下:

do_pollfd(pfd, pt)mask = file->f_op->poll(file, pwait); //即調用驅動中的poll函數(在寫驅動程式時編寫poll函數)poll_wait //其作用為掛載當前進程中可能引起待監測內容狀態變化的等待隊列鏈表頭到poll_table查詢表中,具體實現如下p->qproc(filp, wait_address, p);(p->qproc = __pollwait前面已有初始化)__pollwait(struct file *filp, wait_queue_head_t *wait_address,poll_table *p)(上面展開即為本函數調用){entry->wait_address = wait_address; //掛載進程等待隊列鏈表頭到查詢表add_wait_queue(wait_address, &entry->wait);}

除此以外,poll驅動函數還會根據條件判斷事件是否發生,發生則返回非零的mask掩碼,即為真,count++,並退出休眠;

下面是一個poll驅動函數的例子:

static unsigned forth_drv_poll(struct file *file, poll_table *wait){unsigned int mask = 0;poll_wait(file, &button_waitq, wait); // 將button_waitq等待鏈表頭加入wait查詢表if (ev_press) //判斷事件是否發生,發生了則返回非零,即真;mask |= POLLIN | POLLRDNORM;return mask;}

注釋1-2:

1. 此處主要目的為初始化函數指標,使其指向__pollwait函數,在poll驅動函數中將調用poll_wait,而該函數中將調用__pollwait函數將當前進程掛到等待隊列中,

2. __pollwait函數中有這麼兩句:entry->wait_address = wait_address; add_wait_queue(wait_address, &entry->wait);用於將當前進程中可能引起監測內容變化的等待隊列鏈表頭掛到查詢表中,table->pt->qproc= __pollwait就就是初始化table->pt->qproc函數指標 。

從上述分析可知,poll即使只有一個描述符就緒,也要遍曆整個集合。如果集合中活躍的描述符很少,遍曆過程的開銷就會變得很大,而如果集合中大部分的描述符都是活躍的,遍曆過程的開銷又可以忽略。因此集合中大部分的描述符都是活躍的情況下,poll的使用效率高。每次使用者空間調用poll函數時,都要將全部的資料複製到核心,複製資料增加了開銷

本文參考:http://watter1985.iteye.com/blog/1614039

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.