EPOLL的簡單使用

2021-06-29 06:34:09 字數 2940 閱讀 5584

epoll是linux下的乙個處理多路i/o復用的機制,基於事件通知,能夠高效的處理多個socket連線。

使用epoll,基本的函式只有三個:

(1)建立:epoll_create

(2)控制:epoll_ctl

(3)監聽:epoll_wait

2.1 建立

函式原型:

int epoll_create(int size)
函式開啟乙個epoll的檔案描述符,用於其他epoll函式呼叫。關閉的時候使用close函式。

2.2 控制

函式原型:

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
函式用於 新增/刪除/修改 需要監聽的socket。

引數1是epoll_create返回的控制代碼。

引數2在三個巨集定義中選擇:

epoll_ctl_add:新增需要監聽的socket和事件

epoll_ctl_mod:修改監聽的事件

epoll_ctl_del:移除監聽目標

引數3是操作的目標socket。

引數4是操作的事件引數:

typedef

union epoll_data epoll_data_t;

struct epoll_event ;

需要關注的事件:

epollin:當目標socket有資料到來時觸發。

epollout:當目標socket可寫進觸發。

epollerr:出錯時觸發。

epollhup:對方socket掛起時觸發。

epollet:使用邊緣觸發(edgetriggered)方式。預設是水平觸發(leveltriggered)。

2.3 監聽

函式原型:

int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
引數2是乙個epoll_event陣列,用來儲存收到的資訊。

引數3是陣列大小。

引數4是超時時間,單位毫秒。

返回值是有事件發生的socket數量。

#include 

#include

#include

#include

#include

#include

#define port 2999

#define epoll_size 2048

#define buffer_size 1024

int epoll_fd;

int listen_fd;

int create_listen_socket()

struct sockaddr_in addr;

addr.sin_family = af_inet;

addr.sin_port = htons(port);

addr.sin_addr.s_addr = inaddr_any;

int len = sizeof(addr);

if (-1 == bind(fd, (struct sockaddr*)&addr, len))

listen(fd, 10);

printf("waiting for connections...\n");

return fd;

}void my_epoll_add(int fd)

void on_accept()

}int on_read(int fd)

return -1;

}else

if(n == 0)else

}return0;}

int main(int argn, char **argv)

epoll_fd = epoll_create(epoll_size);

my_epoll_add(listen_fd);

int i, count, fd, ev, timeout = 1000;

struct epoll_event events[epoll_size];

for (;;)

ev = events[i].events;

if ((ev & epollhup) || (ev & epollerr))

if (ev & epollin)else

}else

if(ev & epollout)}}

}close(epoll_fd);

close(listen_fd);

return

0;}

邊緣觸發,就是狀態發生改變時才觸發。

水平觸發,則是狀態存在就一直會觸發。

對於epollin來說,就是水平觸發的話,只要socket裡有資料可讀,還沒讀完,則每次呼叫epoll_wait都會觸發。

而在邊緣觸發下,如果一次呼叫沒有把資料都讀完的話,則下次呼叫不會觸發,要直到下次對方有資料進來時才能繼續。而要想一次把資料讀完,則必須把socket設定成非阻塞,要不然程式就卡在read的地方了。

對於epollout來說,比較難理解。因為讀資料是被動的,可以監聽很正常,而發資料應該是個主動的過程,如何算作監聽呢?

在水平觸發下,如果設定了epollout,那麼只要socket緩衝區足夠空間,就會一直觸發可寫狀態。

而邊緣觸發下,設定了epollout,會在連線時觸發一次,然後在下次狀態由不可寫轉化為可寫時才觸發。寫緩衝區滿了的情況下會出現不可寫的狀態。

更多的時候,是程式自己呼叫epoll_ctl改變狀態來觸發寫事件,統一傳送資料,從而可以減少呼叫核心write的次數。

epoll使用簡單分析

前面說了下select和poll的優缺點及使用,現在說說linux最新的epoll機制,同樣,如有不足或錯誤之處,還請各位道友指導 epoll機制共有三個函式 epoll create int size 建立乙個epoll實體,size是提示核心內部結構的大小,並無大礙 size在linux ker...

Linux中epoll簡單使用

epoll是linux核心為處理大批量控制代碼而作了改進的poll,是linux下多路復用io介面select poll的增強版本,它能顯著減少程式在大量併發連線中只有少量活躍的情況下的系統cpu利用率。epoll預設的工作模式是level triggered,簡稱lt即水平觸發模式。是一種預設的工...

簡單的epoll模型

水平觸發模式 include include include include include include include include include int main int argc,const char ar struct sockaddr in serv addr socklen t ...