1. 什麼是IO
IO (Input/Output,輸入\輸出)即資料的讀取(接收)或寫入(發送)操作,通常使用者程序中的一個完整IO分為兩階段:使用者程序空間<–>核心空間、核心空間<–>裝置空間(磁盤、網絡等)。IO有記憶體IO、網絡IO和磁盤IO三種,通常我們說的IO指的是後兩者
LINUX中程序無法直接操作I/O裝置,其必須通過系統調用請求kernel來協助完成I/O動作;核心會為每個I/O裝置維護一個緩沖區。
對于一個輸入操作來說,程序IO系統調用後,核心會先看緩沖區中有沒有相應的緩存資料,沒有的話再到裝置中讀取,因為裝置IO一般速度較慢,需要等待;核心緩沖區有資料則直接複制到程序空間
是以,對于一個網絡輸入操作通常包括兩個不同階段:
(1 )等待網絡資料到達網卡→讀取到核心緩沖區,資料準備好;
(2 )從核心緩沖區複制資料到程序空間
《UNIX網絡程式設計》說得很清楚,5種IO模型分别是阻塞IO模型、非阻塞IO模型、IO複用模型、信号驅動的IO模型、異步IO模型
1. 阻塞IO模型
程序發起IO系統調用後,程序被阻塞,轉到核心空間處理,整個IO處理完畢後傳回程序。操作成功則程序擷取到資料
例如:
小明去火車站買票,排隊三天買到一張退票。
耗費:在車站吃拉撒睡3天,其他事一件沒幹
2. 非阻塞IO模型
程序發起IO系統調用後,如果核心緩沖區沒有資料,需要到IO裝置中讀取,程序傳回一個錯誤而不會被阻塞;程序發起IO系統調用後,如果核心緩沖區有資料,核心就會把資料傳回給程序。
對于上面的非阻塞IO模型來說,核心資料沒準備好需要程序阻塞的時候,就傳回一個錯誤,以使得程序不被阻塞
例如:
小明去火車站買票,隔12小時去火車站問有沒有退票,三天後買到一張票。
耗費:往返車站6次,路上6小時,其他時間做了好多事
3. IO複用模型
多個的程序的IO可以注冊到一個複用器( select)上,然後用一個程序調用該select,select會監聽所有注冊進來的IO;
如果select監聽的IO在核心緩沖區都沒有可讀資料,select調用程序會被阻塞;而當任一 IO在核心緩沖區中有可用資料時,select調用就會傳回;
而後select調用程序可以自己或通知另外的程序(注冊程序)來再次發起讀取IO,讀取核心中準備好的資料
典型應用: select、 poll、 epoll三種方案,nginx都可以選擇使用這三個方案
events {
worker_ connections 1024;
use epoll;
}
select、poll、 epoll在Linux中IO複用 的實作方式主要有
select, poll和epoll
Select:注冊IO、阻塞掃描,監聽的IO最大連接配接數不能多于FD_ SIZE;
Poll:原理和Select相似,沒有數量限制,但IO數量大掃描線性性能下降;
Epoll :事件驅動不阻塞, mmap實作核心與使用者空間的消息傳遞,數量很大,Linux2.6後核心支援
例如:
l.select/poll
小明去火車站買票,委托黃牛,黃牛三天内買到票,然後打便所有人要買票人的電話找到小明,小明去火車站交錢領票。
耗費:往返車站2次,路上2小時,黃牛手續費100元,等待通知3小時
2.epoll
小明去火車站買票,委托黃牛,黃牛買到後即通知小明去領,然後小明去火車站交錢領票。
耗費:往返車站2次,路上2小時,黃牛手續費100元,無需打電話
4. 信号驅動IO模型
當程序發起一個IO操作,會向核心注冊一個信号處理函數,然後程序傳回不阻塞;當核心資料就緒時會發送一個信号給程序,程序便在信号處理函數中調用IO讀取資料
例如:
小明去火車站買票,給售票員留下電話,有票後,售票員電話通知小明,然後小明去火車站交錢領票。
耗費:往返車站2次,路上2小時,免黃牛費100元,無需打電話
5. 異步IO模型
當程序發起一個IO操作,程序傳回(不阻塞),但也不能傳回結果;核心把整個IO處理完後,會通知程序結果。如果IO操作成功則程序直接擷取到資料
例如:
小明去火車站買票,給售票員留下電話,有票後,售票員電話遇知小明并快遞送票上門。
耗費:往返車站1次,路上1小時,免黃牛費100元,無需打電話
nginx相比于apache有更高的并發,可以接收處理更多的通路請求,這得益于IO模型
同步I/O引起程序阻塞,直到I/O操作完成
異步I/O不會引起程序阻塞
阻塞式I/O, 非阻塞I/O, I/O複用由于都導緻了請求程序阻塞,是以均屬于同步I/O。
nginx高并發使用的是epoll的方式,提供給使用者通路,複制資料的一些操作交由核心完成。自身做的事情越少接待的使用者請求就越多。