用戶程序自己判斷
# 文件描述符列表矾克,對應(yīng)的事件
fd_list = []
# 循環(huán)
while 1:
for fd in fd_list:
# 將fd從用戶態(tài)拷貝到內(nèi)核態(tài)
if fd可讀 or fd可寫:
執(zhí)行操作
判斷文件描述符可讀可寫狀態(tài),要將當(dāng)前文件描述符從用戶態(tài)內(nèi)存拷貝到內(nèi)核態(tài)內(nèi)存捏鱼,會存在開銷执庐。
select
偽代碼
# 文件描述符
fd_list = []
# bitmap映射,完整映射fd_list导梆,010101的樣式轨淌,最大1024位
bitmap = []
while 1:
# 將整個文件描述符列表全部從用戶態(tài)拷貝到內(nèi)核態(tài)
select(bitmap)
for i in bitmap:
if i 對應(yīng)的fd可讀或可寫:
執(zhí)行當(dāng)前fd的讀寫操作
優(yōu)點(diǎn)
- 全量拷貝,每次拷貝都是有資源消耗的看尼,select一次拷貝所有文件描述符递鹉,假設(shè)有1024個文件描述符,用戶自己寫藏斩,要拷貝1024次躏结,而用select只需要拷貝一次
- 由內(nèi)核監(jiān)聽文件描述符狀態(tài)
缺點(diǎn)
- 長度限制,最長只能1024位(雖然可以通過配置去修改狰域,但太長了又會導(dǎo)致循環(huán)過長)
- 文件描述符不可重用(因?yàn)闀梦籦itmap對應(yīng)的節(jié)點(diǎn))
- 用戶態(tài) <-->內(nèi)核態(tài)之間拷貝會有開銷
- O(n)時間復(fù)雜度
poll
工作原理和select相同媳拴,區(qū)別就是select用的bitmap黄橘,poll用的是pollfd結(jié)構(gòu)體
pollfd結(jié)構(gòu)體
struct pollfd {
int fd; # 文件描述符
short events; # 事件
short revents;
}
偽代碼
# 文件描述符的準(zhǔn)備
pollfd_list = []
while 1:
# 用戶態(tài)到內(nèi)核態(tài)的拷貝
poll(pollfd_list)
for i in pollfd_list:
如果當(dāng)前文件描述符可讀或可寫
執(zhí)行讀寫
優(yōu)點(diǎn)(相較select)
- 相對于select的1024的bitmap大小限制,pollfds是一個數(shù)組屈溉,理論上沒有大小限制
- 文件描述符可重用(因?yàn)橹皇侵梦籶ollfd里的revents)
缺點(diǎn)
- 用戶態(tài) <-->內(nèi)核態(tài)之間拷貝會有開銷
- O(n)時間復(fù)雜度
epoll
偽代碼
# 創(chuàng)建白板
epfd = epoll_create(10)
for i in epfd:
# 往白板上寫內(nèi)容(文件描述符塞关,事件)
epoll_ctl(i)
while 1:
# 申請一塊內(nèi)存空間,用戶態(tài)和內(nèi)核態(tài)共享
nfds = epoll_wait()
for i in nfds:
1. 將需要操作(事件觸發(fā)了)的文件描述符(假設(shè)m個)往前排
2.返回需要處理的事件個數(shù)子巾,假設(shè)m個
3.直接讀取共享內(nèi)存的前m個文件描述符
4.對讀取出來的文件描述符做操作
優(yōu)點(diǎn)(相較poll或select)
- 因?yàn)樯暾埩艘粔K用戶態(tài)和內(nèi)核態(tài)可共享內(nèi)存空間帆赢,所以不存在用戶態(tài)<->內(nèi)核態(tài)的拷貝
- O(1)的時間復(fù)雜度