Linux下select和poll的用法

來源:互聯網
上載者:User
Linux下select和poll的用法轉載自:http://blog.csdn.net/dingyuanpu/article/details/5572352

select()函數的作用

    系統調用select和poll的後端實現,用這兩個系統調用來查詢裝置是否可讀寫,或是否處於某種狀態。如果poll為空白,則驅動裝置會被認為即可讀又可寫,傳回值是一個狀態掩碼
如何使用select()函數?
    select()函數的介面主要是建立在一種叫'fd_set'類型的基礎上。它('fd_set') 是一組檔案描述符(fd)的集合。由於fd_set類型的長度在不同平台上不同,因此應該用一組標準的宏定義來處理此類變數:

    fd_set set;
    FD_ZERO(&set);      
    FD_SET(fd, &set);   
    FD_CLR(fd, &set);   
    FD_ISSET(fd, &set); 
     
在過去,一個fd_set通常只能包含少於等於32個檔案描述符,因為fd_set其實只用了一個int的位元向量來實現,在大多數情況下,檢查 fd_set能包括任意值的檔案描述符是系統的責任,但確定你的fd_set到底能放多少有時你應該檢查/修改宏FD_SETSIZE的值。*這個值是系統相關的*,同時檢查你的系統中的select() 的man手冊。有一些系統對多於1024個檔案描述符的支援有問題。[譯者註: Linux就是這樣的系統!你會發現sizeof(fd_set)的結果是128(*8 = FD_SETSIZE=1024) 儘管很少你會遇到這種情況。]

select的基本介面十分簡單:

    int select(int nfds, fd_set *readset, fd_set *writeset,

               fd_set *exceptset, struct timeval *timeout); 
其中:

nfds    
     需要檢查的檔案描述符個數,數值應該比是三組fd_set中最大數
     更大,而不是實際檔案描述符的總數。
readset   
     用來檢查可讀性的一組檔案描述符。
writeset
     用來檢查可寫性的一組檔案描述符。
exceptset
     用來檢查意外狀態的檔案描述符。(註:錯誤並不是意外狀態)
timeout
     NULL指標代表無限等待,否則是指向timeval結構的指標,代表最
     長等待時間。(如果其中tv_sec和tv_usec都等於0, 則檔案描述符
     的狀態不被影響,但函數並不掛起)
     
函數將返迴響應操作的對應操作檔案描述符的總數,且三組資料均在恰當位置被修改,只有響應操作的那一些沒有修改。接著應該用FD_ISSET宏來尋找返回的檔案描述符組。

這裡是一個簡單的測試單個檔案描述符可讀性的例子:

     int isready(int fd)
     {
         int rc;
         fd_set fds;
         struct timeval tv;
   
         FD_ZERO(&fds);
         FD_SET(fd,&fds);
        //tv.tv_sec = tv.tv_usec = 0;
   
        //rc = select(fd+1, &fds, NULL, NULL, &tv);
         rc = select(fd+1, &fds, NULL, NULL, NULL);
         if (rc < 0)
           return -1;
   
         return FD_ISSET(fd,&fds) ? 1 : 0;
      }
     
當然如果我們把NULL指標作為fd_set傳入的話,這就表示我們對這種操作的發生不感興趣,但select() 還是會等待直到其發生或者超過等待時間。

[譯者註:在Linux中,timeout指的是程式在非sleep狀態中度過的時間,而不是實際上過去的時間,這就會引起和非Linux平台移植上的時間不等問題。移植問題還包括在System V風格中select()在函數退出前會把timeout設為未定義的 NULL狀態,而在BSD中則不是這樣, Linux在這點上遵從System V,因此在重複利用timeout指標問題上也應該注意]

 

Linux

下select調用的過程:
1.使用者層應用程式調用select(),底層調用poll())
2.核心層調用sys_select() ------> do_select()
  最終調用檔案描述符fd對應的struct file類型變數的struct file_operations *f_op的poll函數。
  poll指向的函數返回當前可否讀寫的資訊。
  1)如果當前可讀寫,返回讀寫資訊。
  2)如果當前不可讀寫,則阻塞進程,並等待驅動程式喚醒,重新調用poll函數,或逾時返回。
3.驅動需要實現poll函數。
  當驅動發現有資料可以讀寫時,通知核心層,核心層重新調用poll指向的函數查詢資訊。
  poll_wait(filp,&wait_q,wait)    // 此處將當前進程加入到等待隊列中,但並不阻塞
  在中斷中使用wake_up_interruptible(&wait_q)喚醒等待隊列

 

 

 

select()函數的作用

    系統調用select和poll的後端實現,用這兩個系統調用來查詢裝置是否可讀寫,或是否處於某種狀態。如果poll為空白,則驅動裝置會被認為即可讀又可寫,傳回值是一個狀態掩碼
如何使用select()函數?
    select()函數的介面主要是建立在一種叫'fd_set'類型的基礎上。它('fd_set') 是一組檔案描述符(fd)的集合。由於fd_set類型的長度在不同平台上不同,因此應該用一組標準的宏定義來處理此類變數:

    fd_set set;
    FD_ZERO(&set);      
    FD_SET(fd, &set);   
    FD_CLR(fd, &set);   
    FD_ISSET(fd, &set); 
     
在過去,一個fd_set通常只能包含少於等於32個檔案描述符,因為fd_set其實只用了一個int的位元向量來實現,在大多數情況下,檢查 fd_set能包括任意值的檔案描述符是系統的責任,但確定你的fd_set到底能放多少有時你應該檢查/修改宏FD_SETSIZE的值。*這個值是系統相關的*,同時檢查你的系統中的select() 的man手冊。有一些系統對多於1024個檔案描述符的支援有問題。[譯者註: Linux就是這樣的系統!你會發現sizeof(fd_set)的結果是128(*8 = FD_SETSIZE=1024) 儘管很少你會遇到這種情況。]

select的基本介面十分簡單:

    int select(int nfds, fd_set *readset, fd_set *writeset,

               fd_set *exceptset, struct timeval *timeout); 
其中:

nfds    
     需要檢查的檔案描述符個數,數值應該比是三組fd_set中最大數
     更大,而不是實際檔案描述符的總數。
readset   
     用來檢查可讀性的一組檔案描述符。
writeset
     用來檢查可寫性的一組檔案描述符。
exceptset
     用來檢查意外狀態的檔案描述符。(註:錯誤並不是意外狀態)
timeout
     NULL指標代表無限等待,否則是指向timeval結構的指標,代表最
     長等待時間。(如果其中tv_sec和tv_usec都等於0, 則檔案描述符
     的狀態不被影響,但函數並不掛起)
     
函數將返迴響應操作的對應操作檔案描述符的總數,且三組資料均在恰當位置被修改,只有響應操作的那一些沒有修改。接著應該用FD_ISSET宏來尋找返回的檔案描述符組。

這裡是一個簡單的測試單個檔案描述符可讀性的例子:

     int isready(int fd)
     {
         int rc;
         fd_set fds;
         struct timeval tv;
   
         FD_ZERO(&fds);
         FD_SET(fd,&fds);
        //tv.tv_sec = tv.tv_usec = 0;
   
        //rc = select(fd+1, &fds, NULL, NULL, &tv);
         rc = select(fd+1, &fds, NULL, NULL, NULL);
         if (rc < 0)
           return -1;
   
         return FD_ISSET(fd,&fds) ? 1 : 0;
      }
     
當然如果我們把NULL指標作為fd_set傳入的話,這就表示我們對這種操作的發生不感興趣,但select() 還是會等待直到其發生或者超過等待時間。

[譯者註:在Linux中,timeout指的是程式在非sleep狀態中度過的時間,而不是實際上過去的時間,這就會引起和非Linux平台移植上的時間不等問題。移植問題還包括在System V風格中select()在函數退出前會把timeout設為未定義的 NULL狀態,而在BSD中則不是這樣, Linux在這點上遵從System V,因此在重複利用timeout指標問題上也應該注意]

 

Linux

下select調用的過程:
1.使用者層應用程式調用select(),底層調用poll())
2.核心層調用sys_select() ------> do_select()
  最終調用檔案描述符fd對應的struct file類型變數的struct file_operations *f_op的poll函數。
  poll指向的函數返回當前可否讀寫的資訊。
  1)如果當前可讀寫,返回讀寫資訊。
  2)如果當前不可讀寫,則阻塞進程,並等待驅動程式喚醒,重新調用poll函數,或逾時返回。
3.驅動需要實現poll函數。
  當驅動發現有資料可以讀寫時,通知核心層,核心層重新調用poll指向的函數查詢資訊。
  poll_wait(filp,&wait_q,wait)    // 此處將當前進程加入到等待隊列中,但並不阻塞
  在中斷中使用wake_up_interruptible(&wait_q)喚醒等待隊列

 

 

 

相關文章

聯繫我們

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