說明
系列文章:http://www.jianshu.com/p/594441fb9c9e
本文完全參考自《Netty權威指南(第2版)》,李林峯著。
Linux 網絡 I/O 模型
Linux內核將所有的外部設備都看做文件來操作,對文件的讀寫會調用內核的系統命令,返回一個file descriptor(fd,文件描述符)。而對一個socket的讀寫也會有相應的描述符,稱爲socketfd(socket描述符),指向內核中的一個結構體。
UNIX提供了5種I/O模型:
- 阻塞I/O模型:在進程中調用recvfrom,系統直到數據包到達且被複制到應用進程的緩衝區或發生錯誤才返回,在此期間一直會阻塞等待。進程在調用recvfrom開始到它返回的整段時間內都是被阻塞的,所以被稱爲阻塞I/O模型。
- 非阻塞I/O模型:recvfrom從應用層到內核時,如果該緩衝區沒有數據,直接返回錯誤,一般對非阻塞I/O模型進行輪詢狀態檢查,看內核是否有數據到來。
- I/O複用模型:Linux提供
select/poll
,進程將一個或多個fd傳遞給select/poll系統調用,阻塞在select操作上。select/poll順序掃描fd是否準備就緒,而且支持的fd數量很有限。epoll是基於事件驅動方式代替循環掃描,性能更高;當有fd就緒時,立即回調函數rollback。 - 信號驅動I/O模型:系統調用sigaction執行信號處理函數(此係統調用立即返回,進程繼續工作,它是非阻塞的)。當數據準備就緒時,爲該進程生成一個SIGIO信號,通過信號回調通知應用程序調用recvfrom來讀取數據。
- 異步I/O:告知內核啓動某個操作,並讓內核
在整個操作完成後
通知我們。與信號驅動模型的主要區別:信號驅動I/O由內核通知我們何時可以開始一個I/O操作;異步I/O模型由內核通知我們I/O操作何時已經完成。
I/O 多路複用技術
作用
在I/O編程過程中,當需要同時處理多個客戶端接入請求時,有兩種處理方式:
- 多線程
- I/O多路複用技術
那麼I/O多路複用技術有什麼好處呢?
把多個I/O的阻塞,複用到同一個select的阻塞上,從而使得系統通過單線程來同時處理多個客戶端請求
,節省系統資源。
應用場景
- 服務器需要同時處理多個處於監聽狀態或連接狀態的套接字;
- 服務器需要同時處理多種網絡協議的套接字。
支持 I/O 多路複用的模型有哪些?
- select(有缺陷)
- pselect
- poll
- epoll(使用)
epoll 有哪些優點?
- 支持一個進程打開的socket描述符不受限制
- I/O效率不會隨着FD數目的增加而線性下降
- 使用mmap加速內核與用戶空間的消息傳遞
- epoll的API更加簡單
Java 的 I/O 演進
Java的I/O在1.4以前版本並不好,僅有非常基本的功能。
JDK 1.0 ~ JDK 1.3
1.0 ~ 1.3 中的Java I/O類庫相當原始,很多UNIX網絡編程中的概念都沒有體現出來。
JDK 1.4 NIO
JDK 1.4中,NIO正式隨JDK發佈,新增了java.nio包,提供了異步I/O開發的API和類庫
。
JDK 1.7 NIO 2.0
將原來的NIO類庫進行了升級,成爲NIO 2.0。