select 是用於 IO 多路轉接的一個系統呼叫函式。 在 C 語言中，該系統呼叫在 sysselecth 或 unistdh 中宣告，語法如下： int select int nfds fd_set readfds fd_set writefds fd_set errorfds struct timeval timeout 引數 描述 nfds sets 的檔案描述符的最大值 readfds fd_set 型別，包含了需要檢查是否可讀的描述符，輸出時表示哪些描述符可讀。可為 NULL。 writefds fd_set 型別，包含了需要檢查是否可寫的描述符，輸出時表示哪些描述符可寫。可為 NULL。 errorfds fd_set 型別，包含了需要檢查是否出錯的描述符，輸出時表示哪些描述符出錯。可為 NULL。 timeout struct timeval 型別的結構體，表示等待檢查完成的最長時間。 為了維護 fd_set 型別的引數，會使用下面四個宏：FD_SET FD_CLR FD_ZERO 和 FD_ISSET 。 返回值： 這個函式將返回描述符集的個數， 如果超時返回為 0，錯誤則返回 1。 參看： select 2 poll 2 select 與 epoll 的區別 epoll select 概述 epoll 是個模組，由三個系統呼叫組成，核心中由用檔案系統實現 select 是個系統呼叫 結構體定義 typedef union epoll_data void ptr int fd __uint32_t u32 __uint64_t u64 epoll_data_t struct epoll_event __uint32_t events epoll 監聽的事件型別 epoll_data_t data User data variable struct timeval long tv_secsecond long tv_usecminisecond typedef struct fd_set u_int fd_count int fd_array FD_SETSIZE fd_array 可 SIZE8 個 socket 可用的事件 EPOLLIN ：表示對應的檔案描述符可以讀； EPOLLOUT：表示對應的檔案描述符可以寫； EPOLLPRI： 表示對應的檔案描述符有緊急的資料可讀； EPOLLERR： 表示對應的檔案描述符發生錯誤； EPOLLHUP：表示對應的檔案描述符被結束通話； EPOLLET： ET 的 epoll 工作模式； fd_set 有三種類型： readfds writefds exceptionfds 操作函式 三個系統呼叫：epoll_create epoll_ctl epoll_wait 一個系統呼叫：select 四個宏 FD_ZERO FD_SET FD_CLR FD_ISSET 執行模式 邊沿觸發 ET、狀態觸發 LT 狀態觸發 執行過程 int fd epoll_create 1 建立一個 epoll 例項，引數可以是任意正整數 struct epoll_event events xxxBepoll 例項將發生的事件寫入該陣列 while 1int nfds epoll_wait 等待事件發生 for int i0 infds iend for end while struct timeval tv fd_set rfds tv50 設定超時 while 1FD_ZERO rfds if select continue for int i0imaxfds i 結束 for 迴圈 結束 while 迴圈 優點 1）epoll_wait 返回的都是有效資料，可直接從 struct epoll_event 中獲取事件，效率高。 缺點 每次 select 有資料要遍歷全部 socket 注意事項 每次取事件後，要重新註冊此 socket 的事件 epoll。epoll_ctl 每次 select 之前要重置 rfds 的值。FD_ZERO 說明：以上無論 epoll_create fd_set 都受限於系統中單個程序能夠開啟的檔案控制代碼數。 示例 include stdioh include stdlibh include stringh include systypesh include syssocketh include netinetinh include netdbh include sysselecth include fcntlh include unistdh include errnoh define PORT 9421 function prototypes void die const char int main int argc char argv int sockfd new maxfd on 1 nready i struct addrinfo res0 res hints char buffer BUFSIZ fd_set master readfds ssize_t nbytes void memset hints 0 sizeof struct addrinfo hintsai_family AF_INET hintsai_socktype SOCK_STREAM hintsai_protocol IPPROTO_TCP hintsai_flags AI_PASSIVE if 1 getaddrinfo NULL PORT hints res0 die getaddrinfo for res res0 res res resai_next if 1 sockfd socket resai_family resai_socktype resai_protocol perror socket continue if 1 setsockopt sockfd SOL_SOCKET SO_REUSEADDR charon sizeof int perror setsockopt continue if 1 bind sockfd resai_addr resai_addrlen perror bind continue break if 1 sockfd exit EXIT_FAILURE freeaddrinfo res0 if 1 listen sockfd 32 die listen if 1 fcntl sockfd F_SETFD O_NONBLOCK die fcntl FD_ZERO master FD_ZERO readfds FD_SET sockfd master maxfd sockfd while 1 memcpy readfds master sizeof master void printf running select n if 1 nready select maxfd1 readfds NULL NULL NULL die select void printf Number of ready descriptor dn nready for i0 imaxfd nready0 i if FD_ISSET i readfds nready if i sockfd void printf Trying to accept new connection sn if 1 new accept sockfd NULL NULL if EWOULDBLOCK errno die accept break else if 1 fcntl new F_SETFD O_NONBLOCK die fcntl FD_SET new master if maxfd new maxfd new else void printf recv data from one of descriptors sn nbytes recv i buffer sizeof buffer 0 if nbytes 0 if EWOULDBLOCK errno die recv break buffer nbytes 0 printf s buffer void printf zi bytes receivedn nbytes close i FD_CLR i master return 0 void die const char msg perror msg exit EXIT_FAILURE 參見 Berkeley 套接字 輪詢 epoll kqueue IOCP 外部連結 CategoryC POSIX 庫 Category 事件 計算機 Category 系統呼叫