int epoll_create(int size);
- 作用:建立一個 epoll 的句柄。
- 參數:size 用來告訴核心監聽的數目大小,核心會根據 size 的大小去申請對應的記憶體。
- 傳回值:成功則傳回新的 epoll 對象的檔案描述符,這個檔案描述符用于後續的 epoll 操作。如果不需要使用這個描述符,使用 close 關閉。失敗傳回 -1 。
int epoll_create1(int flags);
- 作用:建立一個 epoll 的句柄。
- 參數:flags的值是 0,epoll_create1()等同于epoll_create()。但是不再根據 size 大小申請記憶體。而是動态申請記憶體。flasg 還可以使用其他值。
- 傳回值:成功傳回檔案描述符。失敗傳回 -1 。
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
- 作用:事件注冊函數。我個人的了解就是将要監測的目标 fd 添加進 epfd 中。
- 參數:epfd 是 epoll_create 的傳回值。op:添加事件的類型選項。fd:目标檔案描述符(需要監聽的目标)。event 告訴核心需要監聽什麼事。
- 傳回值:成功傳回 0 ,失敗傳回 -1 。
op 宏(添加事件的類型選項)有以下幾種:
EPOLL_CTL_ADD:在 epfd 中注冊新的 fd ,對這個 fd 要監聽的是 event。
EPOLL_CTL_MOD:改變已注冊到 epfd 的 fd 的監聽事件。即改成新的 event。
EPOLL_CTL_DEL:從指定的 epfd 中 删除 fd 檔案描述符。在這種模式中 event 是被忽略的,并且為可以等于 NULL 。
struct epoll_event(需要監聽的事)結構如下:
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
events 宏有以下幾種,可以取他們的并:
EPOLLIN :表示對應的檔案描述符執行讀時;
EPOLLOUT:表示對應的檔案描述符執行寫時;
EPOLLPRI:表示對應的檔案描述符有緊急的資料可讀(這裡應該表示有帶外資料到來);
EPOLLERR:表示對應的檔案描述符發生錯誤;
EPOLLHUP:表示對應的檔案描述符被挂斷;
EPOLLET: 将EPOLL設為邊緣觸發(Edge Triggered)模式,這是相對于水準觸發(Level Triggered)來說的。
EPOLLONESHOT:隻監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL隊列裡
epoll_data 的結構如下:
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
一般用法是這樣的:
struct epoll_event e;
e.data.fd = socket_fd;
e.events = EPOLLIN | EPOLLOUT;
epoll_ctl(events_fd, EPOLL_CTL_MOD, socket_fd, &e);
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
- 作用:等待 epfd 中的事件。類似于select()調用。
- 參數:events 用來從核心得到事件的集合。maxevents 告知核心有多少個 events,必須要大于0。timeout 是用來制定epoll_wait 會阻塞多少毫秒的。
關于 events 的用法一般是這樣的:
struct epoll_event events[100000]; // 一個數組
// num 告知使用者有多少個事件被監聽到,并且這些事件放在 events 數組裡了
int num = epoll_wait(epfd, events, 100000, 0);
// 循環檢視 num 個事件
for (int i = 0; i < num; ++i) {
if (events[i].events & (EPOLLIN | EPOLLPRI)) {
// 表示對應的檔案描述符執行讀;即,events[i].data.fd 執行讀
// ...
} else if (events[i].events & EPOLLOUT) {
// 表示對應的檔案描述符執行寫;即,events[i].data.fd 執行寫
// ...
} else{
// ...
}
}
參考:
https://www.jianshu.com/p/ee381d365a29