epoll多路復用壓力測試

2021-10-10 07:38:06 字數 3934 閱讀 5689

epoll相對於select、poll效能優越相當之多,可以說是二者結合加強版本,我們可以設想一下,假如有100w個tcp連線,那麼每次有資料過來了,select、poll都需要去從第乙個到最後乙個進行依次遍歷,而epoll會講佇列排序講發生事件放在前面,後面的就不用遍歷了,所以準確的說處理幾千的連線可以用select、poll但是太多了就不行,而且select、poll都是從使用者態拷貝到核心態,需要花費大量的時間,這樣比較起來epoll效能就相當的高了。

struct eventpoll 

;

我們在呼叫epoll_create時,核心除了幫我們在epoll檔案系統裡建了個file結點,在核心cache裡建了個紅黑樹用於儲存以後epoll_ctl傳來的socket外,還會再建立乙個rdllist雙向鍊錶,用於儲存準備就緒的事件,當epoll_wait呼叫時,僅僅觀察這個rdllist雙向煉表裡有沒有資料即可。有資料就返回,沒有資料就sleep,等到timeout時間到後即使鍊錶沒資料也返回。所以,epoll_wait非常高效。

如果rdllist鍊錶不為空,則這裡的事件複製到使用者態記憶體(使用共享記憶體提高效率)中,同時將事件數量返回給使用者。因此epoll_waitx效率非常高。epoll_ctl在向epoll物件中新增、修改、刪除事件時,從rbr紅黑樹中查詢事件也非常快,也就是說epoll是非常高效的,它可以輕易地處理百萬級別的併發連線。

#include

intepoll_ctl

(int epfd,

int op,

int fd,

struct epoll_event *ev)

;

系統呼叫epoll_ctl()能夠修改由檔案描述符epfd所代表的epoll例項中的興趣列表。若成功返回0,若出錯返回-1。

第乙個引數epfd是epoll_create()的返回值; 第二個引數op用來指定需要執行的操作,它可以是如下幾種值:

epoll_ctl_add:將描述符fd新增到epoll例項中的興趣列表中去。對於fd上我們感興趣的事件,都指定在ev所指向的 結構體中。如果我們試圖向興趣列表中新增乙個已存在的檔案描述符,epoll_ctl()將出現eexist錯誤;

epoll_ctl_mod:修改描述符上設定的事件,需要用到由ev所指向的結構體中的資訊。如果我們試圖修改不在興趣列表 中的檔案描述符,epoll_ctl()將出現enoent錯誤;

poll_ctl_del:將檔案描述符fd從epfd的興趣列表中移除,該操作忽略引數ev。如果我們試圖移除乙個不在epfd的興 趣列表中的檔案描述符,epoll_ctl()將出現enoent錯誤。關閉乙個檔案描述符會自動將其從所有的epoll例項的興趣列表 移除;

第三個引數fd指明了要修改興趣列表中的哪乙個檔案描述符的設定。該引數可以是代表管道、fifo、套接字、posix訊息隊 列、inotify例項、終端、裝置,甚至是另乙個epoll例項的檔案描述符。但是,這裡fd不能作為普通檔案或目錄的檔案描述符;

第四個引數ev是指向結構體epoll_event的指標,結構體的定義如下:

typedef

union epoll_data epoll_data_t;

struct epoll_event

;

#include

#include

#include

#include

#include

#include

#include

#include

#include

void

handler_events

(int epfd,

struct epoll_event revs,

int num,

int listen_sock)

printf

("get a new link![%s:%d]\n"

,inet_ntoa

(client.sin_addr)

,ntohs

(client.sin_port));

//因為只是乙個http協議:連線成功後,下面就是要 請求和響應

// 而伺服器端響應之前:要先去讀客戶端要請求的內容

ev.events = epollin;

ev.data.fd = new_sock;

epoll_ctl

(epfd,epoll_ctl_add,new_sock,

&ev)

;continue;}

// 如果是普通檔案描述符,則呼叫read提供讀取資料的服務

if(revs[i]

.events & epollin)

else

if( s ==0)

else

// s = -1 失敗了

continue;}

// 伺服器端給客戶端響應: 寫

if( revs[i]

.events & epollout )}}

intstartup

(int port )

// 2. 解決time_wait時,伺服器不能重啟問題;使伺服器可以立即重啟

int opt =1;

setsockopt

(sock,sol_socket,so_reuseaddr,

&opt,

sizeof

(opt));

struct sockaddr_in local;

local.sin_family = af_inet;

local.sin_addr.s_addr =

htonl

(inaddr_any)

;// 位址為任意型別

local.sin_port =

htons

(port)

;// 這裡的埠號也可以直接指定8080

// 3. 繫結埠號if(

bind

(sock,

(struct sockaddr *

)&local,

sizeof

(local)

)<0)

// 4. 獲得監聽套接字if(

listen

(sock,5)

<0)

return sock;

}int

main

(int argc,

char

* ar**)

// 2. 獲得監聽套接字

int listen_sock =

startup

(atoi

("8899"))

;//埠號傳入的時候是以字串的形式傳入的,需要將其轉為整型

// 3. 初始化結構體----監聽的結構列表

struct epoll_event ev;

ev.events = epollin;

//關心讀事件

ev.data.fd = listen_sock;

// 關心的描述檔案描述符

// 4. epoll的事件註冊函式---新增要關心的檔案描述符的唯讀事件

epoll_ctl

(epfd,epoll_ctl_add,listen_sock,

&ev)

;struct epoll_event revs[

128]

;int n =

sizeof

(revs)

/sizeof

(revs[0]

);int timeout =

3000

;int num =0;

while(1

)}close

(epfd)

;close

(listen_sock)

;return0;

}

epoll多路復用

1 基本知識 epoll是在2.6核心中提出的,是之前的select和poll的增強版本。相對於select和poll來說,epoll更加靈活,沒有描述符限制。epoll使用乙個檔案描述符管理多個描述符,將使用者關係的檔案描述符的事件存放到核心的乙個事件表中,這樣在使用者空間和核心空間的copy只需...

多路復用 epoll

這是乙個基於epoll多路復用的服務端 include include include include include include include include include includeint recv data int fd,char buff else if errno eintr ...

select多路復用壓力測試

1 shell指令碼 bin bash bin bash for i 1 i 1100 i i 1 do.a echo i sleep 0.005 done echo 8 cat test.log grep f wc l cat test.log grep o wc l echo 2 客戶端 inc...