可以睡眠的poll

來源:互聯網
上載者:User

在file_operations中有許多的回呼函數,正是這些回呼函數實現了vfs,vfs提供了一個機制,這些回呼函數提供了不同的策略,等於說實現了vfs,照理說這些函數不應該有任何限制,但是唯獨一個poll回呼函數與眾不同,它不能睡眠,這是為何呢?

     除了poll以外的回呼函數都擁有直接的語義,比如read就是讀,write就是寫,因此系統調用層可以直接將執行路徑交給vfs,比如在sys_read函數中,幾乎做了簡單的判斷之後就馬上調用了真本文件系統的file_operations的read函數,但是poll函數比較特殊,它並沒有簡單的語義,其實它就是輪詢,可是它不像read,write那樣系統調用層和vfs層那麼統一,poll在vfs層的意思就是“看看這個檔案是否有動作”,但是在系統調用層的意義就是“看看這些檔案中哪個有動作”,這就是不同,為了將系統調用層的語義平滑的過度到vfs層,就必須在系統調用和vfs只見插入機制,這個機制實現了poll,當然還包括select。在poll的實現中,靠的是進程的狀態來同步睡眠/喚醒動作的,它並不是在將進程加入睡眠隊列後馬上睡眠,而是不睡眠等到所有poll的檔案描述符均排入佇列後再睡眠,其實僅僅是左一個調度罷了,總體架構如下:

for (;;)

       set_current_state(TASK_INTERRUPTIBLE)

   
       for each fd to poll

           ask driver if I/O can happen

           add current process to driver wait queue

        if one or more fds are ready

           break

      schedule_timeout_range(...)

注意,這裡是在一開始就將進程的狀態設定為TASK_INTERRUPTIBLE但是不睡眠,在中間的for迴圈中陸續將進程加入到睡眠隊列,到了最後才切換進程,等於說就是睡眠了,看看這個糟糕的實現,在設定了進程TASK_INTERRUPTIBLE狀態後那麼大一會才將進程切換,這很是醜陋,醜陋的本質原因就是vfs實現的poll是poll一個檔案描述符,但是系統調用的語義是poll一大堆的檔案描述符,在沒有必要添加適配機制的情況下,只好用進程狀態來實現了,2.6.29核心實在是看不下去這個局面了,於是提出了poll和別的file_operations的回呼函數一樣,也可以睡眠,並且可以用傳統的睡眠喚醒函數來喚醒進程:

+static int pollwake(wait_queue_t
*wait, unsigned mode, int sync, void *key)

+{

+     struct
poll_wqueues *pwq = wait->private;

+     DECLARE_WAITQUEUE(dummy_wait,
pwq->polling_task);

+

+     set_mb(pwq->triggered,
1);

+

+     /*
perform the default wake up operation */

+     return
default_wake_function(&dummy_wait, mode, sync, key);

+}

static void __pollwait(struct file
*filp, wait_queue_head_t *wait_address, poll_table *p)

 {

-      struct
poll_table_entry *entry = poll_get_entry(p);

+     struct
poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);

+     struct
poll_table_entry *entry = poll_get_entry(pwq);

      if
(!entry)

             return;

      get_file(filp);

      entry->filp
= filp;

      entry->wait_address
= wait_address;

-      init_waitqueue_entry(&entry->wait,
current);

+     init_waitqueue_func_entry(&entry->wait,
pollwake);

+     entry->wait.private
= pwq;

      add_wait_queue(wait_address,
&entry->wait);

 }

+int poll_schedule_timeout(struct
poll_wqueues *pwq, int state,

+                     ktime_t *expires, unsigned long slack)

+{

+     int
rc = -EINTR;

+

+     set_current_state(state);

+     if
(!pwq->triggered)

+            rc
= schedule_hrtimeout_range(expires, slack, HRTIMER_MODE_ABS);

+     __set_current_state(TASK_RUNNING);

+

+     /*
clear triggered for the next iteration */

+     pwq->triggered
= 0;

+

+     return
rc;

+}

 

int do_select(int n, fd_set_bits
*fds, s

      for
(;;) {

             unsigned
long *rinp, *routp, *rexp, *inp, *outp, *exp;

-             set_current_state(TASK_INTERRUPTIBLE);

             inp
= fds->in; outp = fds->out; exp = fds->ex;

             rinp
= fds->res_in; routp = fds->res_out; rexp = fds->res_ex;

@@ -411,10 +436,10 @@ int
do_select(int n, fd_set_bits *fds, s

                    to
= &expire;

             }

-             if
(!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))

+            if
(!poll_schedule_timeout(&table, TASK_INTERRUPTIBLE,

+                                    to, slack))

                    timed_out
= 1;

      }

-      __set_current_state(TASK_RUNNING);

      poll_freewait(&table);

我們可以看到在這個可睡眠的poll的補丁中,去掉了刻意為了適配加入的設定進程狀態的語句,加入了統一的linux的睡眠/喚醒機制,poll_schedule_timeout是個新加入的函數,實際上它就是poll中的睡眠函數,和wait_event沒有本質區別的,這樣的話,加入這些函數,poll的實現和別的回呼函數變得統一起來的。

     實際上,我發現在2.6.29核心中,代碼變得更加統一了,核心邏輯變得更加統一了,和前一篇文章我談到的cred從task_struct中分離一樣,poll可睡眠的意義也十分的大,比如將來為了加入新的機制要大改代碼,起碼file_operations中的回呼函數都是統一的,這樣就可以將之獨立成一個模組而不用和別的模組雜糅。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.