多路I O轉接之epoll模型

2021-07-04 17:17:40 字數 3529 閱讀 9314

epoll是linux下多路復用io介面select/poll的增強版本,它能顯著提高程式在大量併發連線中只有少量活躍的情況下的系統cpu利用率,因為它會復用檔案描述符集合來傳遞結

果而不用迫使開發者每次等待事件之前都必須重新準備要被偵聽的檔案描述符集合,另一點原因就是獲取事件的時候,它無須遍歷整個被偵聽的描述符集,只要遍歷那些被核心io事件非同步喚醒而加入ready佇列的描述符集合就行了,因此效能得到很大的提高。對於多檔案描述符而且都處於大量活躍情況下,其效能提公升的並不高,效能和poll差不多。

1.首先要設定系統最大開啟檔案描述符限制(ubuntu 系統)

輸入ulimit -n 4096 可以設定開啟檔案描述符個數的,這是系統預設最大開啟檔案描述符個數,如果超過這個就會報錯。

下面介紹通過修改系統配置檔案,來改變這一預設值。修改後需要重啟系統才能生效。

*表示所有使用者  nofile 表示最大開啟檔案個數 soft 表示軟限制 hard 硬限制。soft限制不能超過硬限制。hard值不能大於系統file-max值。

epoll 模型及相關api

#include int epoll_create(int size);//引數size用來告訴核心監聽的檔案描述符個數

//(確切誰最大併發數量大小),跟記憶體大小有關,linux核心用一顆紅黑樹去維護,返回乙個檔案控制代碼

//控制某個epoll監控的檔案描述符上的事件:註冊(相當於把要監聽的檔案描述符插入到樹中)、修改(本身監聽的是寫屬性,修改為讀屬演變為樹的查詢)、

//刪除(刪除樹的節點)。

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

//epfd:為epoll_creat的控制代碼

//op:表示動作,用3個巨集來表示:epoll_ctl_add(註冊新的fd到epfd),epoll_ctl_mod(修改已經註冊的fd的監聽事件),epoll_ctl_del(從epfd刪除乙個fd)

//event告訴核心要監聽的事件

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

typedef union epoll_data

epoll_data_t;

struct epoll_event

;//event事件

//epollin :表示對應的檔案描述符可以讀(包括對端socket正常關閉)

//epollout:表示對應的檔案描述符可以寫

//epollpri:表示對應的檔案描述符有緊急的資料可讀(這裡應該表示有帶外資料到來)

//epollerr:表示對應的檔案描述符發生錯誤

//epollhup:表示對應的檔案描述符被結束通話;

//epollet: 將epoll設為邊緣觸發(edge triggered)模式,這是相對於水平觸發(level triggered)來說的

//epolloneshot:只監聽一次

關於et(edge trigger)和lt(level trigger)

lt是預設工作模式

對於採用lt工作模式的檔案描述符,當epoll_wait()接收到某乙個檔案描述符事件訊息時候可以不立即觸處理該事件,當程式下一次呼叫epoll_wait還會再次接收到該檔案描述符事件訊息,直到該事件被處理。而對於採用et工作模式的檔案描述符,當epoll_wait一旦接收到某乙個檔案描述符訊息,程式必須立即處理該事件,因為後續的epoll_wait呼叫將不再向程式通知這一事件。

#include#include#include #include #include #include #include #include #include#define open_max 1024

int create_listen(int port);//建立監聽socket描述符

int socket_recv(int socket_fd);//處理客戶端訊息

int socket_accept(int listen_st);//接收客服端連線

int run_server(int port);

int create_listen(int port)

if(setsockopt(listen_st,sol_socket,so_reuseaddr,&on,sizeof(on))==-1)

s_addr.sin_port=htons(port);

s_addr.sin_family=af_inet;

s_addr.sin_addr.s_addr=htonl(inaddr_any);

if(bind(listen_st,(struct sockaddr*)&s_addr,sizeof(struct sockaddr_in))==-1)

if (listen(listen_st, 100) == -1) // 設定檔案描述符具有監聽的功能

return listen_st;  

}int socket_recv(int socket_fd)

;    int len=0;

bzero(buf,sizeof(buf));

if((len=recv(socket_fd,buf,sizeof(buf),0))>0)

return len;

}int socket_accept(int listen_st)

else

return conn_st; }

int run_server(int port)

if((epoll_fd=epoll_create(open_max))==-1)//建立乙個樹

struct epoll_event event,ep[open_max];

event.events=epollin|epollerr|epollhup;//事件為讀、出錯、掛起

event.data.fd=listen_st;

epoll_ctl(epoll_fd,epoll_ctl_add,listen_st,&event);

while(1)

for(i=0;i

多路轉接模型 epoll

1.建立乙個epoll控制代碼 int epoll create int size 注意 用完之後,必須呼叫close 關閉 2.註冊epoll事件 int epoll ctl int epfd,int op,int fd,struct epoll event event epoll ctl add...

IO多路轉接 epoll高階

例項三 基於網路c s非阻塞模型的epoll et觸發模式 epoll事件有兩種模型 et模式即edge triggered工作模式。如果我們在第1步將rfd新增到epoll描述符的時候使用了epollet標誌,那麼在第5步調用epoll wait之後將有可能會掛起,因為剩餘的資料還存在於檔案的輸入...

Linux下I O多路轉接之epoll

linux下i o多路轉接之epoll epoll i o event notification facility 在linux的網路程式設計中,很長的時間都在使用select來做事件觸發。在linux新的核心中,有了一種替換它的機制,就是epoll。相比於select,epoll最大的好處在於它不...