select() - Unix、Linux 系統呼叫 - 技術教學
Tutorials Point


  Unix 初學者指南
  Unix Shell 程式設計
  高階 Unix
  Unix 有用參考
  Unix 有用資源
  精選閱讀

版權所有 © 2014 tutorialspoint



  首頁     參考     討論論壇     關於 TP  

select() - Unix、Linux 系統呼叫


previous next AddThis Social Bookmark Button

廣告

名稱

select、pselect、FD_CLR、FD_ISSET、FD_SET、FD_ZERO - 同步 I/O 多路複用

語法

/* According to POSIX.1-2001 */
#include <sys/select.h> 
/* According to earlier standards */
#include <sys/time.h> 
#include <sys/types.h> 
#include <unistd.h> 

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); void FD_CLR(int fd, fd_set *set); int FD_ISSET(int fd, fd_set *set); void FD_SET(int fd, fd_set *set); void FD_ZERO(fd_set *set);

#define _XOPEN_SOURCE 600 #include <sys/select.h>

int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);

描述

select() 和 pselect() 允許程式監視多個檔案描述符,等待一個或多個檔案描述符準備就緒以進行某種型別的 I/O 操作(例如,輸入可能)。如果可以執行相應的 I/O 操作(例如,read(2))而不會阻塞,則檔案描述符被認為已準備就緒。

select() 和 pselect() 的操作相同,但有三個區別

序號描述
(i)select() 使用一個 struct timeval(秒和微秒)型別的超時,而 pselect() 使用一個 struct timespec(秒和納秒)型別的超時。
(ii) select() 可能會更新 timeout 引數以指示剩餘時間。pselect() 不會更改此引數。
(iii) select() 沒有 sigmask 引數,並且其行為類似於使用 NULL sigmask 呼叫 pselect()。

監視三組獨立的檔案描述符。列在 readfds 中的檔案描述符將被監視,以檢視是否有字元可供讀取(更準確地說,檢視讀取是否不會阻塞;特別是,檔案描述符在檔案結束時也已準備就緒),列在 writefds 中的檔案描述符將被監視,以檢視寫入是否不會阻塞,列在 exceptfds 中的檔案描述符將被監視,以檢視異常。退出時,集合會在原地修改以指示哪些檔案描述符實際上更改了狀態。如果沒有任何檔案描述符要監視相應的事件類別,則三組檔案描述符中的每一組都可以指定為 NULL。

提供了四個宏來操作集合。

  • FD_ZERO() 清空集合。

  • FD_SET() 和

  • FD_CLR() 分別將給定的檔案描述符新增到集合中和從集合中移除。

  • FD_ISSET() 測試檔案描述符是否為集合的一部分;

這在 select() 返回後很有用。

nfds 是三組集合中編號最高的描述符加 1。

timeoutselect() 返回之前經過時間的上限。它可以為零,導致 select() 立即返回。(這對於輪詢很有用。)如果 timeout 為 NULL(無超時),則 select() 可以無限期阻塞。

sigmask 是指向訊號掩碼的指標(請參閱 sigprocmask(2));如果它不為 NULL,則 pselect() 首先用 sigmask 指向的訊號掩碼替換當前訊號掩碼,然後執行“select”函式,然後恢復原始訊號掩碼。

除了 timeout 引數精度上的差異外,以下 pselect() 呼叫

ready = pselect(nfds, &readfds, &writefds, &exceptfds,
                    timeout, &sigmask);

等效於原子地執行以下呼叫

sigset_t origmask;

sigprocmask(SIG_SETMASK, &sigmask, &origmask);
ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
sigprocmask(SIG_SETMASK, &origmask, NULL);

需要 pselect() 的原因是,如果要等待訊號或檔案描述符準備就緒,則需要原子測試以防止競爭條件。(假設訊號處理程式設定全域性標誌並返回。然後,在呼叫 select() 之前測試此全域性標誌可能會無限期掛起,如果訊號恰好在測試後但呼叫之前到達。相反,pselect() 允許首先阻塞訊號,處理已到達的訊號,然後使用所需的 sigmask 呼叫 pselect(),從而避免了競爭條件。)

超時

涉及的時間結構在 <sys/time.h> 中定義,如下所示

struct timeval {
    long    tv_sec;         /* seconds */
    long    tv_usec;        /* microseconds */
};

struct timespec {
    long    tv_sec;         /* seconds */
    long    tv_nsec;        /* nanoseconds */
};

(但是,請參見下面關於 POSIX.1-2001 版本的內容。)一些程式碼使用所有三組都為空、n 為零以及非 NULL timeout 呼叫 select() 作為以亞秒精度休眠的相當便攜的方式。

在 Linux 上,select() 會修改 timeout 以反映未休眠的時間;大多數其他實現不會這樣做。(POSIX.1-2001 允許這兩種行為。)這會導致在將讀取 timeout 的 Linux 程式碼移植到其他作業系統時出現問題,以及在將程式碼移植到 Linux 時出現問題,這些程式碼在迴圈中對多個 select() 重複使用 struct timeval 而無需重新初始化它。在 select() 返回後,認為 timeout 未定義。

返回值

如果成功,select() 和 pselect() 將返回三個返回的描述符集中包含的檔案描述符的數量(即,在 readfdswritefdsexceptfds 中設定的位的總數),如果在發生任何有趣的事情之前超時過期,則該數量可能為零。如果出錯,則返回 -1,並且 errno 被相應地設定;集合和 timeout 變得未定義,因此在錯誤後不要依賴其內容。

錯誤

標籤描述
EBADF 在一組中給出了無效的檔案描述符。(可能是已關閉的檔案描述符,或已發生錯誤的檔案描述符。)
EINTR 捕獲到訊號。
EINVAL nfds 為負或 timeout 中包含的值無效。
ENOMEM 無法為內部表分配記憶體。

示例

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int main(void) {
    fd_set rfds;
    struct timeval tv;
    int retval;

    /* Watch stdin (fd 0) to see when it has input. */
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    /* Wait up to five seconds. */
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    retval = select(1, &rfds, NULL, NULL, &tv);
    /* Don’t rely on the value of tv now! */

    if (retval == -1)
        perror("select()");
    else if (retval)
        printf("Data is available now.\n");
        /* FD_ISSET(0, &rfds) will be true. */
    else
        printf("No data within five seconds.\n");
    return 0;
}

符合標準

select() 符合 POSIX.1-2001 和 4.4BSD

pselect() 在 POSIX.1g 和 POSIX.1-2001 中定義。



previous next Printer Friendly

廣告


  

廣告



廣告