日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

IO:select、poll、epoll

發(fā)布時(shí)間:2025/3/21 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IO:select、poll、epoll 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、什么是IO?

我們都知道unix世界里,一切皆文件,而文件是什么呢?文件就是一串二進(jìn)制流,不管socket,還是FIFO、管道、終端,對(duì)我們來(lái)說(shuō),一切都是文件,一切都是流。在信息交換的過(guò)程中,我們都是對(duì)這些流進(jìn)行數(shù)據(jù)的收發(fā)操作,簡(jiǎn)稱為I/O操作(input and output),往流中讀出數(shù)據(jù),系統(tǒng)調(diào)用read,寫入數(shù)據(jù),系統(tǒng)調(diào)用write。

二、文件描述符

那么計(jì)算機(jī)中這么多流,我們是如何知道要操作哪個(gè)流呢?

這時(shí)候我們需要有一個(gè)能夠?qū)ξ募M(jìn)行定位的標(biāo)識(shí)符,那么文件描述符就應(yīng)運(yùn)而生。文件描述符是內(nèi)核為了高效管理已經(jīng)被打開(kāi)的文件所創(chuàng)建的索引,他是一個(gè)從0開(kāi)始的整數(shù),程序所有執(zhí)行的I/O操作都是通過(guò)文件描述符進(jìn)行的。其中,在程序剛剛啟動(dòng)時(shí),0,1,2三個(gè)文件描述符已經(jīng)被占用了,0代表標(biāo)準(zhǔn)輸入設(shè)備stdin(比如鍵盤),1代表標(biāo)準(zhǔn)輸出設(shè)備stdout(顯示器),2代表標(biāo)準(zhǔn)錯(cuò)誤stderr.POSIX標(biāo)準(zhǔn)要求每次打開(kāi)文件時(shí)(含socket)必須使用當(dāng)前進(jìn)程中最小可用的文件描述符號(hào)碼,因此再打開(kāi)一個(gè)文件,它的文件描述符會(huì)是3。
既然文件描述符是文件的索引,那么它有沒(méi)有最大限制呢?對(duì)的,文件描述符是系統(tǒng)的一個(gè)重要的資源,實(shí)際中最大打開(kāi)的文件數(shù)是系統(tǒng)內(nèi)存的10%,這個(gè)是系統(tǒng)級(jí)限制,有系統(tǒng)就會(huì)有用戶,用戶級(jí)限制是單個(gè)進(jìn)程最大打開(kāi)的文件數(shù),一般是1024,可以使用ulimit -n命令查看。
系統(tǒng)是如何通過(guò)文件描述符定位到文件的呢?
系統(tǒng)為每一個(gè)進(jìn)程維護(hù)了一個(gè)文件描述符表,這是一個(gè)進(jìn)程級(jí)的文件描述符表,它通過(guò)文件描述符所對(duì)應(yīng)的文件指針指向系統(tǒng)級(jí)的打開(kāi)文件描述符表中的一個(gè)打開(kāi)文件句柄,句柄中存儲(chǔ)了打開(kāi)文件相應(yīng)的全部信息,包括文件偏移量、狀態(tài)標(biāo)示、訪問(wèn)模式文件類型以及文件屬性等等,其中有一個(gè)inode指針,它指向了i-node表?中該文件的表項(xiàng)。

三、阻塞與非阻塞

為了讓大家能順利掌握IO復(fù)用,請(qǐng)?jiān)试S我再嘮叨一下阻塞與非阻塞。
什么是程序的阻塞呢?想象這種情形,比如你等快遞,但快遞一直沒(méi)來(lái),你會(huì)怎么做?有兩種方式:
快遞沒(méi)來(lái),我可以先去睡覺(jué),然后快遞來(lái)了給我打電話叫我去取就行了。(非阻塞忙輪詢)
快遞沒(méi)來(lái),我就不停的給快遞打電話說(shuō):擦,怎么還沒(méi)來(lái),給老子快點(diǎn),直到快遞來(lái)。(阻塞)
很顯然,你無(wú)法忍受第二種方式,不僅耽擱自己的時(shí)間,也會(huì)讓快遞很想打你。
而在計(jì)算機(jī)世界,這兩種情形就對(duì)應(yīng)阻塞和非阻塞忙輪詢。
非阻塞忙輪詢:數(shù)據(jù)沒(méi)來(lái),進(jìn)程就不停的去檢測(cè)數(shù)據(jù),直到數(shù)據(jù)來(lái)。
阻塞:數(shù)據(jù)沒(méi)來(lái),啥都不做,直到數(shù)據(jù)來(lái)了,才進(jìn)行下一步的處理。
????先說(shuō)說(shuō)阻塞,為了了解阻塞是如何進(jìn)行的,我們來(lái)討論緩沖區(qū),以及內(nèi)核緩沖區(qū),最終把I/O事件解釋清楚。

緩沖區(qū)的引入是為了減少頻繁I/O操作而引起頻繁的系統(tǒng)調(diào)用(你知道它很慢的),當(dāng)你操作一個(gè)流時(shí),更多的是以緩沖區(qū)為單位進(jìn)行操作,這是相對(duì)于用戶空間而言。對(duì)于內(nèi)核來(lái)說(shuō),也需要緩沖區(qū)。

因?yàn)橐粋€(gè)線程只能處理一個(gè)套接字的I/O事件,如果想同時(shí)處理多個(gè),可以利用非阻塞忙輪詢的方式,偽代碼如下:

while true { for i in stream[]

{ if i has data read until unavailable } }

我們只要把所有流從頭到尾查詢一遍,就可以處理多個(gè)流了,但這樣做很不好,因?yàn)槿绻械牧鞫紱](méi)有I/O事件,白白浪費(fèi)CPU時(shí)間片。正如有一位科學(xué)家所說(shuō),計(jì)算機(jī)所有的問(wèn)題都可以增加一個(gè)中間層來(lái)解決,同樣,為了避免這里cpu的空轉(zhuǎn),我們不讓這個(gè)線程親自去檢查流中是否有事件,而是引進(jìn)了一個(gè)代理(一開(kāi)始是select,后來(lái)是poll),這個(gè)代理很牛,它可以同時(shí)觀察許多流的I/O事件,如果沒(méi)有事件,代理就阻塞,線程就不會(huì)挨個(gè)挨個(gè)去輪詢了,偽代碼如下:

while true { select(streams[]) //這一步死在這里,知道有一個(gè)流有I/O事件時(shí),才往下執(zhí)行

?for i in streams[] { if i has data read until unavailable } }

四、 IO多路復(fù)用

I/O多路復(fù)用 (單個(gè)線程,通過(guò)記錄跟蹤每個(gè)I/O流(sock)的狀態(tài),來(lái)同時(shí)管理多個(gè)I/O流 。)

重要的事情再說(shuō)一遍: I/O multiplexing 這里面的multiplexing 指的其實(shí)是在單個(gè)線程通過(guò)記錄跟蹤每一個(gè)Sock(I/O流)的狀態(tài)(對(duì)應(yīng)空管塔里面的Fight progress strip槽)來(lái)同時(shí)管理多個(gè)I/O流.

發(fā)明它的原因,是盡量多的提高服務(wù)器的吞吐能力。

是不是聽(tīng)起來(lái)好拗口,看個(gè)圖就懂了


在同一個(gè)線程里面, 通過(guò)撥開(kāi)關(guān)的方式,來(lái)同時(shí)傳輸多個(gè)I/O流, (學(xué)過(guò)EE的人現(xiàn)在可以站出來(lái)義正嚴(yán)辭說(shuō)這個(gè)叫“時(shí)分復(fù)用”了)。

什么,你還沒(méi)有搞懂“一個(gè)請(qǐng)求到來(lái)了,nginx使用epoll接收請(qǐng)求的過(guò)程是怎樣的”,

多看看這個(gè)圖就了解了。提醒下,ngnix會(huì)有很多鏈接進(jìn)來(lái), epoll會(huì)把他們都監(jiān)視起來(lái),然后像撥開(kāi)關(guān)一樣,誰(shuí)有數(shù)據(jù)就撥向誰(shuí),然后調(diào)用相應(yīng)的代碼處理。


select, poll, epoll 都是I/O多路復(fù)用的具體的實(shí)現(xiàn),之所以有這三個(gè)鬼存在,其實(shí)是他們出現(xiàn)是有先后順序的。

I/O多路復(fù)用這個(gè)概念被提出來(lái)以后, select是第一個(gè)實(shí)現(xiàn) (1983 左右在BSD里面實(shí)現(xiàn)的)。

select 被實(shí)現(xiàn)以后,很快就暴露出了很多問(wèn)題。

select 會(huì)修改傳入的參數(shù)數(shù)組(事件到來(lái)相應(yīng)的位置1,這個(gè)操作由內(nèi)核完成),這個(gè)對(duì)于一個(gè)需要調(diào)用很多次的函數(shù),是非常不友好的。

select 如果任何一個(gè)sock(I/O stream)出現(xiàn)了數(shù)據(jù),select 會(huì)返回所有的sock,但是并不會(huì)告訴你是那個(gè)sock上有數(shù)據(jù),于是你只能自己一個(gè)一個(gè)的找,10幾個(gè)sock可能還好,要是幾萬(wàn)的sock每次都找一遍,這個(gè)無(wú)謂的開(kāi)銷就頗有海天盛筵的豪氣了。(每次都要去遍歷查找到底是哪個(gè)描述符有事件到來(lái)
select 只能監(jiān)視1024個(gè)鏈接, 這個(gè)跟草榴沒(méi)啥關(guān)系哦,linux 定義在頭文件中的,參見(jiàn)FD_SETSIZE。
select 不是線程安全的,如果你把一個(gè)sock加入到select, 然后突然另外一個(gè)線程發(fā)現(xiàn),尼瑪,這個(gè)sock不用,要收回。對(duì)不起,這個(gè)select 不支持的,如果你喪心病狂的竟然關(guān)掉這個(gè)sock, select的標(biāo)準(zhǔn)行為是。。呃。。不可預(yù)測(cè)的, 這個(gè)可是寫在文檔中的哦.
?
于是14年以后(1997年)一幫人又實(shí)現(xiàn)了poll, poll 修復(fù)了select的很多問(wèn)題,比如
poll 去掉了1024個(gè)鏈接的限制,于是要多少鏈接呢, 主人你開(kāi)心就好。
poll 從設(shè)計(jì)上來(lái)說(shuō),不再修改傳入數(shù)組,不過(guò)這個(gè)要看你的平臺(tái)了,所以行走江湖,還是小心為妙。
其實(shí)拖14年那么久也不是效率問(wèn)題, 而是那個(gè)時(shí)代的硬件實(shí)在太弱,一臺(tái)服務(wù)器處理1千多個(gè)鏈接簡(jiǎn)直就是神一樣的存在了,select很長(zhǎng)段時(shí)間已經(jīng)滿足需求。

但是poll仍然不是線程安全的, 這就意味著,不管服務(wù)器有多強(qiáng)悍,你也只能在一個(gè)線程里面處理一組I/O流。你當(dāng)然可以那多進(jìn)程來(lái)配合了,不過(guò)然后你就有了多進(jìn)程的各種問(wèn)題。

于是5年以后, 在2002, 大神 Davide Libenzi 實(shí)現(xiàn)了epoll.

epoll 可以說(shuō)是I/O 多路復(fù)用最新的一個(gè)實(shí)現(xiàn),epoll 修復(fù)了poll 和select絕大部分問(wèn)題, 比如:

epoll 現(xiàn)在是線程安全的。
epoll 現(xiàn)在不僅告訴你sock組里面數(shù)據(jù),還會(huì)告訴你具體哪個(gè)sock有數(shù)據(jù),你不用自己去找了。
?

?

select

函數(shù)介紹:
  該函數(shù)準(zhǔn)許進(jìn)程指示內(nèi)核等待多個(gè)事件中的任何一個(gè)發(fā)送,并只在有一個(gè)或多個(gè)事件發(fā)生或經(jīng)歷一段指定的時(shí)間后才喚醒。函數(shù)原型如下:

?

include <sys select.h="">

include <sys time.h="">

?

int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout)</sys></sys>

返回值:就緒描述符的數(shù)目,超時(shí)返回0,出錯(cuò)返回-1
函數(shù)參數(shù)介紹如下:
(1)第一個(gè)參數(shù)maxfdp1指定待測(cè)試的描述字個(gè)數(shù),它的值是待測(cè)試的最大描述字加1(因此把該參數(shù)命名為maxfdp1),描述字0、1、2…maxfdp1-1均將被測(cè)試。
因?yàn)槲募枋龇菑?開(kāi)始的。
(2)中間的三個(gè)參數(shù)readset、writeset和exceptset指定我們要讓內(nèi)核測(cè)試讀、寫和異常條件的描述字。如果對(duì)某一個(gè)的條件不感興趣,就可以把它設(shè)為空指針。struct fd_set可以理解為一個(gè)集合,這個(gè)集合中存放的是文件描述符(可以看為是socket的事件),可通過(guò)以下四個(gè)宏進(jìn)行設(shè)置:

void FD_ZERO(fd_set *fdset); //清空集合
void FD_SET(int fd, fd_set *fdset); //將一個(gè)給定的文件描述符加入集合之中
void FD_CLR(int fd, fd_set *fdset); //將一個(gè)給定的文件描述符從集合中刪除
int FD_ISSET(int fd, fd_set *fdset); // 檢查集合中指定的文件描述符是否可以讀寫

(3)timeout告知內(nèi)核等待所指定描述字中的任何一個(gè)就緒可花多少時(shí)間。其timeval結(jié)構(gòu)用于指定這段時(shí)間的秒數(shù)和微秒數(shù)。

struct timeval{

??????long tv_sec;???//seconds

??????long tv_usec;??//microseconds

};

這個(gè)參數(shù)有三種可能:
(1)永遠(yuǎn)等待下去:僅在有一個(gè)描述字準(zhǔn)備好I/O時(shí)才返回。為此,把該參數(shù)設(shè)置為空指針NULL。
(2)等待一段固定時(shí)間:在有一個(gè)描述字準(zhǔn)備好I/O時(shí)返回,但是不超過(guò)由該參數(shù)所指向的timeval結(jié)構(gòu)中指定的秒數(shù)和微秒數(shù)。
(3)根本不等待:檢查描述字后立即返回,這稱為輪詢。為此,該參數(shù)必須指向一個(gè)timeval結(jié)構(gòu),而且其中的定時(shí)器值必須為0。

?

函數(shù)說(shuō)明:
I/O多路復(fù)用這個(gè)概念被提出來(lái)以后, select是第一個(gè)實(shí)現(xiàn) (1983 左右在BSD里面實(shí)現(xiàn)的)。

select 被實(shí)現(xiàn)以后,很快就暴露出了很多問(wèn)題。
1) 對(duì)socket進(jìn)行掃描時(shí)是線性掃描,即采用輪詢的方法,效率較低。
當(dāng)套接字比較多的時(shí)候,每次select()都要通過(guò)遍歷FD_SETSIZE個(gè)Socket來(lái)完成調(diào)度,不管哪個(gè)Socket是活躍的,都遍歷一遍。這會(huì)浪費(fèi)很多CPU時(shí)間。
2) select 如果任何一個(gè)sock(I/O stream)出現(xiàn)了數(shù)據(jù),select 僅僅會(huì)返回,但是并不會(huì)告訴你是那個(gè)sock上有數(shù)據(jù),于是你只能遍歷所有的socket自己一個(gè)一個(gè)的找
3) select 只能監(jiān)視1024個(gè)鏈接, linux 定義在頭文件中的,參見(jiàn)FD_SETSIZE。
4) 需要維護(hù)一個(gè)用來(lái)存放大量fd的數(shù)據(jù)結(jié)構(gòu),這樣會(huì)使得用戶空間和內(nèi)核空間在傳遞該結(jié)構(gòu)時(shí)復(fù)制開(kāi)銷大。
5) select 不是線程安全的,如果你把一個(gè)sock加入到select, 然后突然另外一個(gè)線程發(fā)現(xiàn),這個(gè)sock不用,要收回。對(duì)不起,這個(gè)select 不支持的,如果你喪心病狂的竟然關(guān)掉這個(gè)sock, select的標(biāo)準(zhǔn)行為是。。呃。。不可預(yù)測(cè)的。


1)這3個(gè)bitmap有大小限制(FD_SETSIZE,常為1024);

2)由于這3個(gè)集合在返回時(shí)會(huì)被內(nèi)核修改,因此我們每次調(diào)用時(shí)都需要重新設(shè)置;

3)我們?cè)谡{(diào)用完成后需要掃描這3個(gè)集合(即掃描所有的socket)才能知道哪些fd的讀/寫事件發(fā)生了,一般情況下全量集合比較大而實(shí)際發(fā)生讀/寫事件的fd比較少,效率比較低下;

4)(將用戶傳入的數(shù)組拷貝到內(nèi)核空間)內(nèi)核在每次調(diào)用時(shí)都需要掃描這3個(gè)fd集合(套接字集合),然后查看哪些fd的事件實(shí)際發(fā)生,并將它傳到設(shè)備等待隊(duì)列。在讀/寫比較稀疏的情況下同樣存在效率問(wèn)題

poll

于是14年以后(1997年)一幫人又實(shí)現(xiàn)了poll, poll 修復(fù)了select的很多問(wèn)題,比如
1) poll 去掉了1024個(gè)鏈接的限制,于是要多少鏈接呢,主人你開(kāi)心就好。
2) poll 從設(shè)計(jì)上來(lái)說(shuō),不再修改傳入所有的數(shù)組(所有的socket),需要傳遞的是一個(gè)pollfd結(jié)構(gòu)的數(shù)組,不過(guò)這個(gè)要看你的平臺(tái)了。

但是poll仍然不是線程安全的,這就意味著,不管服務(wù)器有多強(qiáng)悍,你也只能在一個(gè)線程里面處理一組I/O流。

你當(dāng)然可以那多進(jìn)程來(lái)配合了,不過(guò)然后你就有了多進(jìn)程的各種問(wèn)題。
poll本質(zhì)上和select沒(méi)有區(qū)別,它將用戶傳入的數(shù)組拷貝到內(nèi)核空間然后查詢每個(gè)fd對(duì)應(yīng)的設(shè)備狀態(tài),如果設(shè)備就緒則在設(shè)備等待隊(duì)列中加入一項(xiàng)并繼續(xù)遍歷,如果遍歷完所有fd后沒(méi)有發(fā)現(xiàn)就緒設(shè)備,則掛起當(dāng)前進(jìn)程,直到設(shè)備就緒或者主動(dòng)超時(shí),被喚醒后它又要再次遍歷fd。這個(gè)過(guò)程經(jīng)歷了多次無(wú)謂的遍歷。
?????它沒(méi)有最大連接數(shù)的限制,原因是它是基于鏈表來(lái)存儲(chǔ)的,但是同樣有一個(gè)缺點(diǎn):
1) 大量的fd的數(shù)組被整體復(fù)制于用戶態(tài)和內(nèi)核地址空間之間,而不管這樣的復(fù)制是不是有意義。
2) poll還有一個(gè)特點(diǎn)是“水平觸發(fā)”,如果報(bào)告了fd后,沒(méi)有被處理,那么下次poll時(shí)會(huì)再次報(bào)告該fd。

?

select() 和 poll() 系統(tǒng)調(diào)用的本質(zhì)一樣,poll() 的機(jī)制與 select() 類似,與 select() 在本質(zhì)上沒(méi)有多大差別,管理多個(gè)描述符也是進(jìn)行輪詢,根據(jù)描述符的狀態(tài)進(jìn)行處理,但是 poll()?沒(méi)有最大文件描述符數(shù)量的限制(但是數(shù)量過(guò)大后性能也是會(huì)下降)。poll() 和 select() 同樣存在一個(gè)缺點(diǎn)就是,包含大量文件描述符的數(shù)組被整體復(fù)制于用戶態(tài)和內(nèi)核的地址空間之間,而不論這些文件描述符是否就緒,它的開(kāi)銷隨著文件描述符數(shù)量的增加而線性增大。

epoll

于是5年以后, 在2002, 大神 Davide Libenzi 實(shí)現(xiàn)了epoll.
epoll 可以說(shuō)是I/O 多路復(fù)用最新的一個(gè)實(shí)現(xiàn),epoll 修復(fù)了poll 和select絕大部分問(wèn)題, 比如:
1. 沒(méi)有最大并發(fā)連接的限制,能打開(kāi)的FD的上限遠(yuǎn)大于1024(1G的內(nèi)存上能監(jiān)聽(tīng)約10萬(wàn)個(gè)端口)。
2. 效率提升,不是輪詢的方式,不會(huì)隨著FD數(shù)目的增加效率下降。

只有活躍可用的FD才會(huì)調(diào)用callback函數(shù);即Epoll最大的優(yōu)點(diǎn)就在于它只管你“活躍”的連接,而跟連接總數(shù)無(wú)關(guān),因此在實(shí)際的網(wǎng)絡(luò)環(huán)境中,Epoll的效率就會(huì)遠(yuǎn)遠(yuǎn)高于select和poll。
3. 內(nèi)存拷貝,利用mmap()文件映射內(nèi)存加速與內(nèi)核空間的消息傳遞;即epoll使用mmap減少?gòu)?fù)制開(kāi)銷。(共享內(nèi)存的方式實(shí)現(xiàn))

epoll使用一個(gè)文件描述符管理多個(gè)描述符,將用戶關(guān)系的文件描述符的事件存放到內(nèi)核的一個(gè)事件表中,這樣在用戶空間和內(nèi)核空間的copy只需一次。
原理:epoll支持水平觸發(fā)和邊緣觸發(fā),最大的特點(diǎn)在于邊緣觸發(fā),它只告訴進(jìn)程哪些fd剛剛變?yōu)榫途w態(tài),并且只會(huì)通知一次。還有一個(gè)特點(diǎn)是,epoll使用“事件”的就緒通知方式,通過(guò)epoll_ctl注冊(cè)fd,一旦某個(gè)文件描述符就緒,內(nèi)核就會(huì)采用類似callback的回調(diào)機(jī)制來(lái)激活該fd,epoll_wait便可以收到通知。(此處去掉了遍歷文件描述符,而是通過(guò)監(jiān)聽(tīng)回調(diào)的的機(jī)制。這正是epoll的魅力所在。)


三種方式總結(jié):

從select那里僅僅知道了,有I/O事件發(fā)生了,卻并不知道是哪那幾個(gè)流(可能有一個(gè),多個(gè),甚至全部),我們只能無(wú)差別輪詢所有流,找出能讀出數(shù)據(jù),或者寫入數(shù)據(jù)的流,對(duì)他們進(jìn)行操作。所以select具有O(n)的無(wú)差別輪詢復(fù)雜度,同時(shí)處理的流越多,無(wú)差別輪詢時(shí)間就越長(zhǎng)。
epoll可以理解為event poll,不同于忙輪詢和無(wú)差別輪詢,epoll會(huì)把哪個(gè)流發(fā)生了怎樣的I/O事件通知我們。所以我們說(shuō)epoll實(shí)際上是事件驅(qū)動(dòng)(每個(gè)事件關(guān)聯(lián)上fd)的,此時(shí)我們對(duì)這些流的操作都是有意義的。(復(fù)雜度降低到了O(1))偽代碼如下:

while true { active_stream[] = epoll_wait(epollfd) for i in active_stream[] { read or write till } }

可以看到,select和epoll最大的區(qū)別就是:select只是告訴你一定數(shù)目的流有事件了,至于哪個(gè)流有事件,還得你一個(gè)一個(gè)地去輪詢,而 epoll會(huì)把發(fā)生的事件告訴你,通過(guò)發(fā)生的事件,就自然而然定位到哪個(gè)流了。不能不說(shuō)epoll跟select相比,是質(zhì)的飛躍,這也是一種犧牲空間,換取時(shí)間的思想,畢竟現(xiàn)在硬件越來(lái)越便宜了。


????表面上看epoll的性能最好,但是在連接數(shù)少并且連接都十分活躍的情況下,select和poll的性能可能比epoll好,畢竟epoll的通知機(jī)制需要很多函數(shù)回調(diào)。
?

總結(jié)

以上是生活随笔為你收集整理的IO:select、poll、epoll的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。