天天看點

select、poll、epoll用法差別與聯系

一、多路IO轉接原理圖

select、poll、epoll用法差別與聯系

二、多路IO轉接select

1.select介紹

Select監聽的檔案描述符受限于FD_SETSIZE,一般為1024,單純改變程序打開的檔案描述個數并不能改變select監聽的檔案描述符個數,由于select采用的是輪詢機制,故而如果用戶端過多的話,效率會比較很低。

2.select控制原語

函數原型:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
           

參數1: int nfds為要監聽的最大問價描述符+1

參數2: 讀 檔案描述符集合 傳入、傳出

參數3: 寫 檔案描述符集合 NULL 傳入、傳出

參數4: 異常 檔案描述符集合 NULL 傳入、傳出

參數5: NULL——永久等; > 0 —— 等待指定時間。

fd_set: 檔案描述符集合 fd_set fds; 位圖

void FD_ZERO(fd_set *set);              清空監聽集合
void FD_SET(int fd, fd_set *set);       将fd添加到監聽集合裡
void FD_CLR(int fd, fd_set *set);       将fd 從 監聽集合中 删除
 int  FD_ISSET(int fd, fd_set *set);    判斷 fd 是否在  監聽的集合
           

傳回值:所有監聽檔案描述符中, 滿足條件的“總”個數。 FD_ISSET( , readfds) –> 1 真

FD_ISSET(, writefds) --> 1 
           

3.使用select的注意事項及适用場景

注意事項

監聽檔案描述符上限 1024,如果需要改變監聽的檔案描述,那麼需要改核心,重新編譯;當用戶端通路量很大,由于輪詢機制,效率會降低;不能使用sleep相關類似事件。

适用場景

智能家居

三、多路IO轉接poll模型

1.poll介紹

poll突破1024檔案描述上限,實作了 傳入、傳出參數分離。但它所處的位置十分尴尬,處于select和epoll之間,很少有人會直接用它的。

2.poll控制原語

函數原型:

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
           

pollfd結構體:

struct pollfd
{
   int   fd;        監聽的檔案描述符
   short events;    //POLLIN、POLLOUT、POLLERR
   short revents;   poll傳回時滿足該條件的revents == events;
 };
           

參數1: 監聽的檔案描述符所在結構體 struct pollfd 數組。

參數2: 數組元素個數。

參數3: milliseconds 毫秒。

傳回值:跟select 一樣。

四、多路IO轉接epoll模型

1.epoll簡介

epoll是Linux下多路複用IO接口select/poll的增強版本,它能顯著提高程式在大量并發連接配接中隻有少量活躍的情況下的系統CPU使用率,因為它會複用檔案描述符集合來傳遞結果而不用迫使開發者每次等待事件之前都必須重新準備要被偵聽的檔案描述符集合,另一點原因就是擷取事件的時候,它無須周遊整個被偵聽的描述符集,隻要周遊那些被核心IO事件異步喚醒而加入Ready隊列的描述符集合就行了。目前epell是linux大規模并發網絡程式中的熱門首選模型。epoll除了提供select/poll那種IO事件的電平觸發(Level Triggered)外,還提供了邊沿觸發(EdgeTriggered),這就使得使用者空間程式有可能緩存IO狀态,減少epoll_wait/epoll_pwait的調用,提高應用程式效率

2.epoll的控制原語

函數原型1:

int epoll_create(int size); 建立一個 epoll 秘書。      
           

參數:size監聽上限數

傳回值: 檔案描述符: epfd (句柄 — 紅黑樹)

函數原型2:

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)       
           

參數1: epfd create的傳回值(紅黑樹)

參數2: op

EPOLL_CTL_ADD (注冊新的fd到epfd),
EPOLL_CTL_MOD (修改已經注冊的fd的監聽事件),
EPOLL_CTL_DEL (從epfd删除一個fd);
           

參數3:fd 監聽的檔案描述符

參數4:event 結構體的位址(&event)

struct epoll_event
{
    uint32_t  events;  //EPOLLIN、EPOLLOUT、EPOLLERR      
    epoll_data_t data; //使用者資料
};

typedef union epoll_data 
{  
     void        *ptr;
     int          fd;       監聽的檔案描述符。
     uint32_t     u32;
     uint64_t     u64;
 } epoll_data_t;
           

傳回值: 成功0 失敗-1

函數原型3:

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)  阻塞監聽
           

參數1: epfd 紅黑樹的根

參數2: events 【數組】 傳出參數。 内部 struct epoll_event 類的結構體。

參數3: 數組的容量

參數4: 等待毫秒數

傳回值:滿足條件的檔案描述符總個數

3.epoll-ET和 epoll-LT

LT(水準觸發或電平觸發): 緩沖區 如果有沒讀完的資料,epoll_wait 也觸發。

ET(邊緣觸發):緩沖區 如果有沒讀完的資料,epoll_wait 不觸發。 等下一次用戶端再發送資料的時候,觸發。

4.epoll适用場景

效率和并發量

繼續閱讀