本文參考社長(zhǎng)的 TinyWebServer 庖丁解牛
創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括灌南網(wǎng)站建設(shè)、灌南網(wǎng)站制作、灌南網(wǎng)頁(yè)制作以及灌南網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃等。多年來(lái),我們專(zhuān)注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,灌南網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到灌南省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
#include
int epoll_create(int size);
創(chuàng)建一個(gè)指示 epoll 內(nèi)核事件表的文件描述符,該描述符將用作其他 epoll 系統(tǒng)調(diào)用的第一個(gè)參數(shù),此處的 size 參數(shù)不起作用。
#include
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
該函數(shù)用于操作內(nèi)核事件表監(jiān)控的文件描述符上的事件:注冊(cè)、修改、刪除:
epfd
:為 epoll_create 的句柄;op
:表示動(dòng)作,用 3 個(gè)宏來(lái)表示:
EPOLL_CTL_ADD
:注冊(cè)新的 fd 到 epfd;EPOLL_CTL_MOD
:修改已經(jīng)注冊(cè)的 fd 的監(jiān)聽(tīng)事件;EPOLL_CTL_DEL
:從 epfd 刪除一個(gè) fd;event
:告訴內(nèi)核需要監(jiān)聽(tīng)的事件。其中,event
是 epoll_event
結(jié)構(gòu)體指針類(lèi)型,表示內(nèi)核監(jiān)聽(tīng)的事件,具體定義如下:
struct epoll_event {
__uint32_t events;
epoll_data_t data;
};
events
描述事件類(lèi)型,其中 epoll 事件類(lèi)型有以下幾種:
EPOLLIN
:表示對(duì)應(yīng)的文件描述符可讀(包括對(duì)端SOCKET正常關(guān)閉)EPOLLOUT
:表示對(duì)應(yīng)的文件描述符可寫(xiě);EPOLLPRI
:表示對(duì)應(yīng)的文件描述符有緊急的數(shù)據(jù)可讀(這里應(yīng)該表示有帶外數(shù)據(jù)到來(lái))EPOLLERR
:表示對(duì)應(yīng)的文件描述符發(fā)生錯(cuò)誤;EPOLLHUP
:表示對(duì)應(yīng)的文件描述符被掛斷;EPOLLLET
:將 EPOLL 設(shè)置為邊緣觸發(fā)(ET)模式;EPOLLONESHOT
:只監(jiān)聽(tīng)一次事件,當(dāng)監(jiān)聽(tīng)完這次事件之后,如果還需要繼續(xù)監(jiān)聽(tīng)這個(gè) socket 的話,需要再次把這個(gè) socket 加入到 EPOLL 隊(duì)列中。#include
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
該函數(shù)用于等待所監(jiān)控的文件描述符上有事件的產(chǎn)生,返回就緒的文件描述符的個(gè)數(shù)。
events
:用來(lái)存儲(chǔ)內(nèi)核得到的事件的集合;maxevents
:告知內(nèi)核這個(gè) events 有多大,這個(gè)值不能大于創(chuàng)建 epoll_create() 時(shí)的大?。?/li>
timeout
:超時(shí)時(shí)間:
-1
:阻塞;0
:立即返回,非阻塞;>0
:指定毫秒數(shù);調(diào)用函數(shù)
文件描述符數(shù)量
將文件描述符從用戶傳給內(nèi)核:
內(nèi)核判斷就緒的文件描述符:
應(yīng)用程序索引就緒文件描述符:
工作模式:
其實(shí) ET 和 LT 哪個(gè)高效也是針對(duì)不同的任務(wù)而言。
應(yīng)用場(chǎng)景:
LT 水平觸發(fā)模式
Note:
一個(gè)事件只要有,就會(huì)一直觸發(fā)。
socket 上只要有未讀完的數(shù)據(jù),就會(huì)一直產(chǎn)生 EPOLLIN 事件。所以讀完數(shù)據(jù)要移除事件,避免一直觸發(fā)。
ET 邊緣觸發(fā)模式
Note:
只有一個(gè)事件從無(wú)到有,才會(huì)觸發(fā)。
socket 上每新來(lái)一次數(shù)據(jù)就會(huì)觸發(fā)一次,如果某一次觸發(fā)后,未將 socket 上的數(shù)據(jù)全部讀完,也不會(huì)再次觸發(fā),除非再來(lái)一次數(shù)據(jù)。所以必須要一次性讀完所有數(shù)據(jù)。如果未讀完,需要再次將事件注冊(cè),
ET 模式必須配合非阻塞 I/O 實(shí)現(xiàn),因?yàn)?ET 模式會(huì)一次性讀取完所有的數(shù)據(jù),如果是阻塞 I/O 的話,會(huì)導(dǎo)致線程阻塞,影響重新調(diào)用 epoll_wait 來(lái)監(jiān)聽(tīng)其他事件。