大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家講的是國內外串列NOR Flash廠商官網Cross Reference功能。 串列 NOR Flash 是一個相對發展穩定的市場,目前全球市場約 90% 的份額被中國的三家廠商(Winbond華邦/MXIC旺巨集/GigaDevice兆易創新) ...
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
:向內核空間添加,修改,刪除需要監控的fd
epoll_wait
、epoll_pwait
:類似select
函數