IO複用函數select poll epoll

select

#include <sys/select.h>
#include <sys/time.h>
int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout)

返回值:就緒描述符的數目,超時返回0,出錯返回-1

  1. 第一個參數maxfdp1指定待測試的描述字個數,它的值是待測試的最大描述字加1.
  2. 中間的三個參數readset、writeset和exceptset指定我們要讓內核測試讀、寫和異常條件的描述字。如果對某一個的條件不感興趣,就可以把它設爲空指針。struct fd_set可以理解爲一個集合,這個集合中存放的是文件描述符,可通過以下四個宏進行設置:
void FD_ZERO(fd_set *fdset);           //清空集合

void FD_SET(int fd, fd_set *fdset);   //將一個給定的文件描述符加入集合之中

void FD_CLR(int fd, fd_set *fdset);   //將一個給定的文件描述符從集合中刪除

int FD_ISSET(int fd, fd_set *fdset);   // 檢查集合中指定的文件描述符是否可以讀寫 
  1. timeout告知內核等待所指定描述字中的任何一個就緒可花多少時間。其timeval結構用於指定這段時間的秒數和微秒數。
struct timeval{
    long tv_sec;   //seconds
    long tv_usec;  //microseconds
};

poll

#include <poll.h>
int poll ( struct pollfd * fds, unsigned int nfds, int timeout);

返回值:就緒描述符的數目,超時返回0,出錯返回-1

pollfd結構體定義如下:

struct pollfd {
    int fd;         /* 文件描述符 */
    short events;         /* 等待的事件 */
    short revents;       /* 實際發生了的事件 */
} ; 

fd成員指定文件描述符,events成員告訴poll監聽fd上的哪些事件,它是一系列事件的按位或;revents成員則有內核修改,以通知應用程序fd上實際發生了哪些事件.

poll事件類型:

事件 描述
POLLIN 有數據可讀
POLLRDNORM 有普通數據可讀。
POLLRDBAND 有優先數據可讀。
POLLPRI 有緊迫數據可讀。
POLLOUT 寫數據不會導致阻塞。
POLLWRNORM 寫普通數據不會導致阻塞。
POLLWRBAND 寫優先數據不會導致阻塞。
POLLMSGSIGPOLL 消息可用。

此外,revents域中還可能返回下列事件:

事件 描述
POLLER 指定的文件描述符發生錯誤。
POLLHUP 指定的文件描述符掛起事件。
POLLNVAL 指定的文件描述符非法。

epoll

#include <sys/epoll.h>
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
int epoll_create(int size);

返回值:文件描述符,出錯返回-1

創建一個epoll的句柄,size用來告訴內核這個監聽的數目一共有多大,這個參數不同於select()中的第一個參數,給出最大監聽的fd+1的值,參數size並不是限制了epoll所能監聽的描述符最大個數,只是對內核初始分配內部數據結構的一個建議
當創建好epoll句柄後,它就會佔用一個fd值,在linux下如果查看/proc/進程id/fd/,是能夠看到這個fd的,所以在使用完epoll後,必須調用close()關閉,否則可能導致fd被耗盡。

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

返回值:成功返回0,出錯返回-1

函數是對指定描述符fd執行op操作。
- epfd:是epoll_create()的返回值。
- op:表示op操作,用三個宏來表示:添加EPOLL_CTL_ADD,刪除EPOLL_CTL_DEL,修改EPOLL_CTL_MOD。分別添加、刪除和修改對fd的監聽事件。
- fd:是需要監聽的fd(文件描述符)
- epoll_event:是告訴內核需要監聽什麼事,struct epoll_event結構如下:

struct epoll_event {
  __uint32_t events;  /* Epoll events */
  epoll_data_t data;  /* User data variable */
};

//events可以是以下幾個宏的集合:
EPOLLIN :表示對應的文件描述符可以讀(包括對端SOCKET正常關閉);
EPOLLOUT:表示對應的文件描述符可以寫;
EPOLLPRI:表示對應的文件描述符有緊急的數據可讀(這裏應該表示有帶外數據到來);
EPOLLERR:表示對應的文件描述符發生錯誤;
EPOLLHUP:表示對應的文件描述符被掛斷;
EPOLLET: 將EPOLL設爲邊緣觸發(Edge Triggered)模式,這是相對於水平觸發(Level Triggered)來說的。
EPOLLONESHOT:只監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL隊列裏
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

返回值:就緒描述符的數目,超時返回0,出錯返回-1

等待epfd上的io事件,最多返回maxevents個事件。

參數events用來從內核得到事件的集合,maxevents告之內核這個events有多大,這個maxevents的值不能大於創建epoll_create()時的size,參數timeout是超時時間(毫秒,0會立即返回,-1將不確定,也有說法說是永久阻塞)。該函數返回需要處理的事件數目,如返回0表示已超時。

工作模式

epoll對文件描述符的操作有兩種模式:LT(level trigger)和ET(edge trigger)。LT模式是默認模式,LT模式與ET模式的區別如下:
  LT模式:當epoll_wait檢測到描述符事件發生並將此事件通知應用程序,應用程序可以不立即處理該事件。下次調用epoll_wait時,會再次響應應用程序並通知此事件。
  ET模式:當epoll_wait檢測到描述符事件發生並將此事件通知應用程序,應用程序必須立即處理該事件。如果不處理,下次調用epoll_wait時,不會再次響應應用程序並通知此事件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章