前面介紹了NIO中的buffer和Channel,而我們将NIO主要的使用場景還是在網絡環境中,在具體介紹之前我們需要了解下IO的模型

I/O模型需要的基礎
檔案描述符
Linux 的核心将所有外部裝置都看做一個檔案來操作,對一個檔案的讀寫操作會調用核心提供的系統指令(api),傳回一個file descriptor(fd,檔案描述符)。而對一個socket的讀寫也會有響應的描述符,稱為socket fd(socket檔案描述符),描述符就是一個數字,指向核心中的一個結構體(檔案路徑,資料區等一些屬性)。
是以說:在Linux下對檔案的操作是利用檔案描述符(file descriptor)來實作的。
使用者空間和核心空間
為了保證使用者程序不能直接操作核心(kernel),保證核心的安全,操心系統将虛拟空間劃分為兩部分:核心空間和使用者空間
I/O運作過程
我們來看看IO在系統中的運作是怎麼樣的(我們以read為例)
可以發現的是:當應用程式調用read方法時,是需要等待的—>從核心空間中找資料,再将核心空間的資料拷貝到使用者空間的。
這個等待是必要的過程!
下面隻講解用得最多的3個I/0模型:
阻塞I/O
非阻塞I/O
I/O多路複用
阻塞I/O
在程序(使用者)空間中調用recvfrom,其系統調用直到資料包到達且被複制到應用程序的緩沖區中或者發生錯誤時才傳回,在此期間一直等待。
非阻塞I/O
recvfrom從應用層到核心的時候,如果沒有資料就直接傳回一個EWOULDBLOCK錯誤,一般都對非阻塞I/O模型進行輪詢檢查這個狀态,看核心是不是有資料到來。
I/O多路複用
在Linux下對檔案的操作是利用檔案描述符(file descriptor)來實作的。在Linux下它是這樣子實作I/O複用模型的:
調用select/poll/epoll/pselect其中一個函數,傳入多個檔案描述符,如果有一個檔案描述符就緒,則傳回,否則阻塞直到逾時。
當使用者程序調用了select,那麼整個程序會被block;
而同時,kernel會“監視”所有select負責的socket;
當任何一個socket中的資料準備好了,select就會傳回;
這個時候使用者程序再調用read操作,将資料從kernel拷貝到使用者程序(空間)。
是以,I/O 多路複用的特點是通過一種機制一個程序能同時等待多個檔案描述符,而這些檔案描述符其中的任意一個進入讀就緒狀态,select()函數就可以傳回。
select/epoll的優勢并不是對于單個連接配接能處理得更快,而是在于能處理更多的連接配接。