亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 2685 | 回復: 9
打印 上一主題 下一主題

select沒有把進程放入wait queue嗎? [復制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2010-07-22 13:17 |只看該作者 |倒序瀏覽
本帖最后由 kgn28 于 2010-07-22 13:20 編輯

記得看過0.12的select實現(xiàn):
1,檢查文件描述符,調(diào)用fd->ops->poll,測試文件描述符是否準備好。
2,如果沒有,則把自己放到一個wait queue中,然后schedule。
也就是讓自己去睡眠,等待被喚醒,但是看2.6的代碼時,有些不理解:
http://lxr.linux.no/linux+v2.6.33/fs/select.c
  1. 396int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
  2. 397{
  3. 398        ktime_t expire, *to = NULL;
  4. 399        struct poll_wqueues table;
  5. 400        poll_table *wait;
  6. 401        int retval, i, timed_out = 0;
  7. 402        unsigned long slack = 0;
  8. 403
  9. 404        rcu_read_lock();
  10. 405        retval = max_select_fd(n, fds);
  11. 406        rcu_read_unlock();
  12. 407
  13. 408        if (retval < 0)
  14. 409                return retval;
  15. 410        n = retval;
  16. 411
  17. 412        poll_initwait(&table);
  18. 413        wait = &table.pt;
  19. 414        if (end_time && !end_time->tv_sec && !end_time->tv_nsec) {
  20. 415                wait = NULL;
  21. 416                timed_out = 1;
  22. 417        }
  23. 418
  24. 419        if (end_time && !timed_out)
  25. 420                slack = estimate_accuracy(end_time);
  26. 421
  27. 422        retval = 0;
  28. 423        for (;;) {
  29. 424                unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
  30. 425
  31. 426                inp = fds->in; outp = fds->out; exp = fds->ex;
  32. 427                rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex;
  33. 428
  34. 429                for (i = 0; i < n; ++rinp, ++routp, ++rexp) {
  35. 430                        unsigned long in, out, ex, all_bits, bit = 1, mask, j;
  36. 431                        unsigned long res_in = 0, res_out = 0, res_ex = 0;
  37. 432                        const struct file_operations *f_op = NULL;
  38. 433                        struct file *file = NULL;
  39. 434
  40. 435                        in = *inp++; out = *outp++; ex = *exp++;
  41. 436                        all_bits = in | out | ex;
  42. 437                        if (all_bits == 0) {
  43. 438                                i += __NFDBITS;
  44. 439                                continue;
  45. 440                        }
  46. 441
  47. 442                        for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) {
  48. 443                                int fput_needed;
  49. 444                                if (i >= n)
  50. 445                                        break;
  51. 446                                if (!(bit & all_bits))
  52. 447                                        continue;
  53. 448                                file = fget_light(i, &fput_needed);
  54. 449                                if (file) {
  55. 450                                        f_op = file->f_op;
  56. 451                                        mask = DEFAULT_POLLMASK;
  57. 452                                        if (f_op && f_op->poll) {
  58. 453                                                wait_key_set(wait, in, out, bit);
  59. 454                                                mask = (*f_op->poll)(file, wait);
  60. 455                                        }
  61. 456                                        fput_light(file, fput_needed);
  62. 457                                        if ((mask & POLLIN_SET) && (in & bit)) {
  63. 458                                                res_in |= bit;
  64. 459                                                retval++;
  65. 460                                                wait = NULL;
  66. 461                                        }
  67. 462                                        if ((mask & POLLOUT_SET) && (out & bit)) {
  68. 463                                                res_out |= bit;
  69. 464                                                retval++;
  70. 465                                                wait = NULL;
  71. 466                                        }
  72. 467                                        if ((mask & POLLEX_SET) && (ex & bit)) {
  73. 468                                                res_ex |= bit;
  74. 469                                                retval++;
  75. 470                                                wait = NULL;
  76. 471                                        }
  77. 472                                }
  78. 473                        }
  79. 474                        if (res_in)
  80. 475                                *rinp = res_in;
  81. 476                        if (res_out)
  82. 477                                *routp = res_out;
  83. 478                        if (res_ex)
  84. 479                                *rexp = res_ex;
  85. 480                        cond_resched();
  86. 481                }
  87. 482                wait = NULL;
  88. 483                if (retval || timed_out || signal_pending(current))
  89. 484                        break;
  90. 485                if (table.error) {
  91. 486                        retval = table.error;
  92. 487                        break;
  93. 488                }
  94. 489
  95. 490                /*
  96. 491                 * If this is the first loop and we have a timeout
  97. 492                 * given, then we convert to ktime_t and set the to
  98. 493                 * pointer to the expiry value.
  99. 494                 */
  100. 495                if (end_time && !to) {
  101. 496                        expire = timespec_to_ktime(*end_time);
  102. 497                        to = &expire;
  103. 498                }
  104. 499
  105. 500                if (!poll_schedule_timeout(&table, TASK_INTERRUPTIBLE,
  106. 501                                           to, slack))
  107. 502                        timed_out = 1;
  108. 503        }
  109. 504
  110. 505        poll_freewait(&table);
  111. 506
  112. 507        return retval;
  113. 508}
復制代碼
看情形,在for( ; ; )之間,不停的調(diào)用:
1,測試
2,cond_resched()
那分明是:沒有把當前進程放入到wait queue,然后叫其他進程喚醒,而是不停的執(zhí)行,直到被搶占或者文件描述符準備好。不知道我哪里理解錯了???如果是這樣cpu周期不是浪費了嗎???
也就是說調(diào)用select的進程一直是出于running狀態(tài)的了。。。

論壇徽章:
0
2 [報告]
發(fā)表于 2010-07-22 13:53 |只看該作者
在fd->ops->poll里面,如果對應fd沒有需要的事件,就會把current加入等待隊列。
也就是說,current會被加入所有的fd的等待隊列(如果它們都沒有需要的事件的話)。 加入等待隊列的這些waiter管理在table結構里面,退回do_select之前會清理。

在完成對所有fd的poll之后,如果沒有發(fā)現(xiàn)需要的事件,最后會跑到poll_schedule_timeout,current在這里進入睡眠。

論壇徽章:
0
3 [報告]
發(fā)表于 2010-07-22 13:55 |只看該作者
你可以選擇用pause()函數(shù)來實現(xiàn)

論壇徽章:
0
4 [報告]
發(fā)表于 2010-07-22 13:59 |只看該作者
pause():

     pause函數(shù)使調(diào)用進程掛起直到有信號遞達。如果信號的處理動作是終止進程,則進程終止,pause函數(shù)沒有機會返回;如果信號的處理動作是忽略,則進程繼續(xù)處于掛起狀態(tài),pause不返回;如果信號的處理動作是捕捉,則調(diào)用了信號處理函數(shù)之后pause返回-1,errno設置為EINTR,所以pause只有出錯的返回值

   參考《apue2》

論壇徽章:
0
5 [報告]
發(fā)表于 2010-07-22 14:03 |只看該作者
也就是說,current會被加入所有的fd的等待隊列(如果它們都沒有需要的事件的話)。 加入等待隊列的這些waiter管理在table結構里面,退回do_select之前會清理。
回復 2# kouu
這個有代碼為證嗎?我看了字符終端的poll,貌似沒有啊。。。

論壇徽章:
0
6 [報告]
發(fā)表于 2010-07-22 14:29 |只看該作者
先看do_select里面,poll_initwait(&table);

  1. void poll_initwait(struct poll_wqueues *pwq)
  2. {
  3.         init_poll_funcptr(&pwq->pt, __pollwait);
  4.         pwq->polling_task = current;
  5.         pwq->error = 0;
  6.         pwq->table = NULL;
  7.         pwq->inline_index = 0;
  8. }
  9. static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc)
  10. {
  11.         pt->qproc = qproc;
  12. }
復制代碼
這里把 table.pt.qproc 設為 __pollwait, 把polling_task設為current。

再看一下 pipe.c 里面管道的(讀端的)poll函數(shù),pipe_poll:

  1. static unsigned int
  2. pipe_poll(struct file *filp, poll_table *wait)
  3. {
  4.         unsigned int mask;
  5.         struct inode *inode = filp->f_path.dentry->d_inode;
  6.         struct pipe_inode_info *pipe = inode->i_pipe;
  7.         int nrbufs;

  8.         poll_wait(filp, &pipe->wait, wait);

  9.         /* Reading only -- no need for acquiring the semaphore.  */
  10.         nrbufs = pipe->nrbufs;
  11.         mask = 0;
  12.         if (filp->f_mode & FMODE_READ) {
  13.                 mask = (nrbufs > 0) ? POLLIN | POLLRDNORM : 0;
  14.                 if (!pipe->writers && filp->f_version != pipe->w_counter)
  15.                         mask |= POLLHUP;
  16.         }

  17.         if (filp->f_mode & FMODE_WRITE) {
  18.                 mask |= (nrbufs < PIPE_BUFFERS) ? POLLOUT | POLLWRNORM : 0;
  19.                 /*
  20.                  * Most Unices do not set POLLERR for FIFOs but on Linux they
  21.                  * behave exactly like pipes for poll().
  22.                  */
  23.                 if (!pipe->readers)
  24.                         mask |= POLLERR;
  25.         }

  26.         return mask;
  27. }

復制代碼
一開始就會調(diào)用: poll_wait(filp, &pipe->wait, wait);

  1. static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
  2. {
  3.         if (p && wait_address)
  4.                 p->qproc(filp, wait_address, p);
  5. }
復制代碼
這里實際上就是調(diào)用之前初始化的 __pollwait。 再看__pollwait,這里就是加入等待隊列

  1. static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
  2.                                 poll_table *p)
  3. {
  4.         struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
  5.         struct poll_table_entry *entry = poll_get_entry(pwq);
  6.         if (!entry)
  7.                 return;
  8.         get_file(filp);
  9.         entry->filp = filp;
  10.         entry->wait_address = wait_address;
  11.         init_waitqueue_func_entry(&entry->wait, pollwake);
  12.         entry->wait.private = pwq;
  13.         add_wait_queue(wait_address, &entry->wait);
  14. }
復制代碼

論壇徽章:
0
7 [報告]
發(fā)表于 2010-07-22 14:50 |只看該作者
本帖最后由 kgn28 于 2010-07-22 14:52 編輯

回復 2# kouu


   
poll_wait(filp, &pipe->wait, wait);


這里面__pollwait只是把當前進程加入隊列,找了半天沒找到,把當前進程狀態(tài)改變并且schedule將當前進程從運行隊列里面刪除的代碼?
我的意思是類似這樣的:
  1. set_current_state(TASK_INTERRUPTIBLE);
  2. schedule();
復制代碼
只有cond_resched();,這個不會起到修改進程狀態(tài)的作用吧???

論壇徽章:
0
8 [報告]
發(fā)表于 2010-07-22 14:56 |只看該作者
在完成對所有fd的poll之后,如果沒有發(fā)現(xiàn)需要的事件,最后會跑到poll_schedule_timeout,current在這里進入睡眠。
kouu 發(fā)表于 2010-07-22 13:53


在 do_select 里面,大for的最后,poll_schedule_timeout

  1. int poll_schedule_timeout(struct poll_wqueues *pwq, int state,
  2.                           ktime_t *expires, unsigned long slack)
  3. {
  4.         int rc = -EINTR;

  5.         set_current_state(state);
  6.         if (!pwq->triggered)
  7.                 rc = schedule_hrtimeout_range(expires, slack, HRTIMER_MODE_ABS);
  8.         __set_current_state(TASK_RUNNING);

  9.         /*
  10.          * Prepare for the next iteration.
  11.          *
  12.          * The following set_mb() serves two purposes.  First, it's
  13.          * the counterpart rmb of the wmb in pollwake() such that data
  14.          * written before wake up is always visible after wake up.
  15.          * Second, the full barrier guarantees that triggered clearing
  16.          * doesn't pass event check of the next iteration.  Note that
  17.          * this problem doesn't exist for the first iteration as
  18.          * add_wait_queue() has full barrier semantics.
  19.          */
  20.         set_mb(pwq->triggered, 0);

  21.         return rc;
  22. }

復制代碼

論壇徽章:
0
9 [報告]
發(fā)表于 2010-07-22 14:57 |只看該作者
cond_resched(); 是在內(nèi)層的for里面,每poll一個fd就會調(diào)一次。 而睡眠的事情,則應當是poll完所有fd之后的

論壇徽章:
0
10 [報告]
發(fā)表于 2010-07-22 14:59 |只看該作者
回復 8# kouu


    {:3_185:} 終于理解了,謝謝。。。。。。。。。。。。。。。。。。。。。
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP