BIO
BIO(Blocking IO) 又稱同步阻塞IO,一個客戶端由一個執行緒來進行處理

當客戶端建立連接后,服務端會開辟執行緒用來與客戶端進行連接,以下兩種情況會造成IO阻塞:
- 服務端會一直阻塞,直到和客戶端進行連接
- 客戶端也會一直阻塞,直到和服務端進行連接
基于BIO,當連接時,每有一個客戶端,服務就開啟執行緒處理,這樣對資源的占用時非常大的;如果使用線城市來做優化,當大量連接時,服務端也會面臨無空閑執行緒處理的問題,那么怎么設計才能讓單個執行緒能夠處理更多請求,而不是一個,所以NIO就被提出,
NIO
NIO(Non Blocking IO)又稱同步非阻塞IO,服務器實作模式為把多個連接(請求)放入集合中,只用一個執行緒可以處理多個請求(連接),也就是多路復用,
NIO有3大核心組件:
- Buffer:緩沖區,buffer 底層就是陣列
- Channel:通道,channel 類似于流,每個 channel 對應一個 buffer緩沖區
- Selector:多路復用器,channel 會注冊到 selector 上,由 selector 根據 channel 讀寫事件的發生將其交由某個空閑的執行緒處理

這樣就大大提升了連接的數量,用于接收請求,
NIO目前有三個函式(模型)
- select
- poll
- epoll
Select函式
Select 是Linux提供的一個函式,可以將一批fd一次性傳遞給內核,然后由內核去遍歷,來確定哪個fd符合,并提供給用戶空間

Select 函式處理程序
- 將用戶空間的
fd陣列拷貝到內核空間 - 內核空間會遍歷
fd陣列,查看是否有資料到達- 遍歷所有
fd,將當前行程掛到每個fd的等待佇列中 - 當設備收到一條訊息(網路設備)或填寫完檔案資料(磁盤設備)后,會喚醒設備等待佇列上睡眠的行程,隨后
當前行程就會被喚醒
- 遍歷所有
- 遍歷完成后,如果有資料到達,回傳有資料到達的
fd的數量,并對用戶空間的fd做標記 - 如果無資料到達,則
當前行程進入睡眠,當有某個fd有I/O事件或當前行程睡眠超時后,當前行程重新喚醒再次遍歷所有fd檔案 - 用戶空間再此回圈遍歷,沒有標記的
fd不處理,只有標記的fd才會去處理
Select存在的問題
fd數量有限制:單個行程所打開的fd是有限制的,通過FD_SETSIZE設定,默認1024fd拷貝耗時:每次呼叫select,需要將fd陣列從用戶空間拷貝到內核空間- 內核空間遍歷耗時:內核空間通過遍歷的方式,查看
fd是否有資料到達,這是一個同步的程序 - 找到
fd后,回傳的是數量,而不是fd本身:select回傳的是fd的數量,具體是哪個還需要用戶自己遍歷
Poll函式
Poll 也是Linux提供的內核函式,poll 和 select 基本是一致,唯一的區別在于它們支持的fd的數量不一致
- select : 只能監聽 1024 個
fd - poll :無限制,作業系統支持多少,poll 就可以支持多少
Epoll函式
poll解決了select函式的fd數量問題,而epoll解決了select、poll函式其余問題:
fd數量有限制:poll已經解決此問題fd拷貝耗時:內核空間種保存一份fd陣列,無需用戶每次都重新傳入,只需要告訴內核修改的部分即可- 內核空間遍歷耗時:內核空間不再通過遍歷的方式找
fd,而是通過異步 IO 事件喚醒 - 找到
fd后,回傳的是數量,而不是fd本身:內核空間會通過異步 IO 事件,將fd回傳給用戶,用戶無需在遍歷整個fd陣列

因此,epoll提供3 個函式,來處理上述改進的方案:
epoll_create:創建 epoll 句柄epoll_ctl:向內核空間添加,修改,洗掉需要監控的fdepoll_wait、epoll_pwait:類似select函式
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/539584.html
標籤:其他
