高效能伺服器之epoll

2021-08-02 14:19:09 字數 3437 閱讀 8887

什麼是epoll epoll是什麼?是為處理⼤大批量控制代碼⽽而作了改進的poll。它⼏幾乎具備了之前所說的⼀一切優點,被公認為linux2.6下效能最好的多路i/o就緒通 知⽅方法。

epoll的相關系統調⽤用 epoll只有epoll_create,epoll_ctl,epoll_wait 3個系統調⽤用。

1. int epoll_create(int size); 建立⼀乙個epoll的控制代碼。⾃自從linux2.6.8之後,size引數是被忽略的。需要注意的是,當建立好 epoll控制代碼後,它就是會佔⽤用⼀乙個fd值,在linux下如果檢視/proc/程序id/fd/,是能夠看到這 個fd的,所以在使⽤用完epoll後,必須調⽤用close()關閉,否則可能導致fd被耗盡。

2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); epoll的事件註冊函式,它不同於select()是在監聽事件時告訴核心要監聽什麼型別的事件,⽽而 是在這⾥裡先註冊要監聽的事件型別。 第⼀乙個引數是epoll_create()的返回值。 第⼆二個參數列⽰示動作,⽤用三個巨集來表⽰示: epoll_ctl_add:註冊新的fd到epfd中

epoll_ctl_mod:修改已經註冊的fd的監聽事件; epoll_ctl_del:從epfd中刪除⼀乙個fd; 第三個引數是需要監聽的fd。 第四個引數是告訴核心需要監聽什麼事,struct epoll_event結構如下:

struct union epoll_data

struct epoll_event

events可以是以下⼏幾個巨集的集合: epollin :表⽰示對應的⽂檔案描述符可以讀(包括對端socket正常關閉); epollout:表⽰示對應的⽂檔案描述符可以寫; epollpri:表⽰示對應的⽂檔案描述符有緊急的資料可讀(這⾥裡應該表⽰示有帶外資料到來); epollerr:表⽰示對應的⽂檔案描述符發⽣生錯誤; epollhup:表⽰示對應的⽂檔案描述符被結束通話; epollet: 將epoll設為邊緣觸發(edge triggered)模式,這是相對於⽔水平觸發(level triggered)來說的。 epolloneshot:只監聽⼀一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個 socket的話,需要再次把這個socket加⼊入到epoll佇列⾥裡

3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); 收集在epoll監控的事件中已經傳送的事件。引數events是分配好的epoll_event結構體陣列, epoll將會把發⽣生的事件賦值到events陣列中(events不可以是空指標,核心只負責把資料復 製到這個events陣列中,不會去幫助我們在⽤使用者態中分配記憶體)。maxevents告之核心這個 events有多⼤大,這個 maxevents的值不能⼤大於建立epoll_create()時的size,引數timeout是超時 時間(毫秒,0會⽴立即返回,-1將不確定,也有說法說是永久阻塞)。如果函式調⽤用成功, 返回對應i/o上已準備好的⽂檔案描述符數⽬目,如返回0表⽰示已超時。

2.底層結構示意圖:

epoll_create:系統建立就緒佇列和紅黑樹

就緒佇列:系統維護用來就緒事件

epoll_ctl:主要是對紅黑樹中插入,刪除,更改要x檔案v事件

epoll_wait :用來等待就緒事件,返回就緒事件的個數

3.以下**

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

int statup(char*ip,int port)

struct sockaddr_in local;

local.sin_addr.s_addr=inet_addr(ip);

local.sin_port=htons(port);

socklen_t len=sizeof(local);

int b=bind(sock,(struct sockaddr*)&local,len);

if(b<0)

int l=listen(sock,10);

if(l<0)

return sock;

}typedef

struct fd_buf

fd_buf, *fd_buf_p;

void *malloc_fd_buf(int fd)

temp->fd=fd;

return temp;

}void read_fd(int epfd,fd_buf_p fdp)

if(s>0)

else

if(s==0)

free(fdp); //remenber free,!froget

}}void write_msg(int epfd,fd_buf_p fdp)

int accept_sock(int fd)

printf("get a new connect\n");

return newsock;

}int main(int argc,char* argv)

int listen_sock=statup(argv[1],atoi(argv[2]));

int epfd=epoll_create(256);

if(epfd<0)

struct epoll_event evn;

evn.events=epollin;

evn.data.ptr=malloc_fd_buf(listen_sock);

if(epoll_ctl(epfd, epoll_ctl_add, listen_sock,&evn)<0)

struct epoll_event events[20];

int count;

while(1)

//if is lisent_sock

else

if(fdp->fd!=listen_sock)

//is read

if(events[i].events & epollout)

//is write

}//isn"t listensock

}//for i

//break;

}//deflut

break;

}//switch

}//while

return

0;}

高效能伺服器程式設計之epoll

在linux的網路程式設計中,經常使用多執行緒處理高併發的問題,然而linux系統對執行緒數量是有限制的,更重要的是執行緒的排程有系統開銷的,在客戶端數量龐大時,這將是無法接受的問題 另一種處理高併發的方法是使用select來做事件觸發,select實現中,它是採用輪詢來處理的,輪詢的fd數目越多,...

高效能伺服器 epoll驚群與lighttpd改良

關於高效能server,unix網路程式設計 堪稱經典。根據說明,有如下三種相對高效的模型 模型1 最強 乙個程序中有預先建立多個執行緒都阻塞在accept函式 為了免accept驚群,可以在accept前先thread lock 任何乙個監聽執行緒從accept返回得到乙個socket就自己處理這...

高效能伺服器之select

系統提供select函式來實現多路復 用輸 入 輸出模型。select系統調 用是 用來讓我們的程式監視 多個 檔案控制代碼的狀態變化的。程式會停在select這 裡等待,直到被監視的 檔案控制代碼有 乙個或 多個發 生了狀態改變 int select int nfds,fd set readfds...