官术网_书友最值得收藏!

1.1.1 Linux網絡I/O模型簡介

Linux的內核將所有外部設備都看做一個文件來操作,對一個文件的讀寫操作會調用內核提供的系統命令,返回一個file descriptor(fd,文件描述符)。而對一個socket的讀寫也會有相應的描述符,稱為socketfd(socket描述符),描述符就是一個數字,它指向內核中的一個結構體(文件路徑,數據區等一些屬性)。

根據UNIX網絡編程對I/O模型的分類,UNIX提供了5種I/O模型,分別如下。

(1)阻塞I/O模型:最常用的I/O模型就是阻塞I/O模型,缺省情形下,所有文件操作都是阻塞的。我們以套接字接口為例來講解此模型:在進程空間中調用recvfrom,其系統調用直到數據包到達且被復制到應用進程的緩沖區中或者發生錯誤時才返回,在此期間一直會等待,進程在從調用recvfrom開始到它返回的整段時間內都是被阻塞的,因此被稱為阻塞I/O模型,如圖1-1所示。

(2)非阻塞I/O模型:recvfrom從應用層到內核的時候,如果該緩沖區沒有數據的話,就直接返回一個EWOULDBLOCK錯誤,一般都對非阻塞I/O模型進行輪詢檢查這個狀態,看內核是不是有數據到來。如圖1-2所示。

圖1-1 阻塞I/O模型

圖1-2 非阻塞I/O模型

(3)I/O復用模型:Linux提供select/poll,進程通過將一個或多個fd傳遞給select或poll系統調用,阻塞在select操作上,這樣select/poll可以幫我們偵測多個fd是否處于就緒狀態。select/poll是順序掃描fd是否就緒,而且支持的fd數量有限,因此它的使用受到了一些制約。Linux還提供了一個epoll系統調用,epoll使用基于事件驅動方式代替順序掃描,因此性能更高。當有fd就緒時,立即回調函數rollback。如圖1-3所示。

(4)信號驅動I/O模型:首先開啟套接口信號驅動I/O功能,并通過系統調用sigaction執行一個信號處理函數(此系統調用立即返回,進程繼續工作,它是非阻塞的)。當數據準備就緒時,就為該進程生成一個SIGIO信號,通過信號回調通知應用程序調用recvfrom來讀取數據,并通知主循環函數處理數據。如圖1-4所示。

圖1-3 I/O復用模型

圖1-4 信號驅動I/O模型

(5)異步I/O:告知內核啟動某個操作,并讓內核在整個操作完成后(包括將數據從內核復制到用戶自己的緩沖區)通知我們。這種模型與信號驅動模型的主要區別是:信號驅動I/O由內核通知我們何時可以開始一個I/O操作;異步I/O模型由內核通知我們I/O操作何時已經完成。如圖1-5所示。

圖1-5 異步I/O模型

如果想要了解更多的UNIX系統網絡編程知識,可以閱讀《UNIX網絡編程》,里面有非常詳細的原理和API介紹。對于大多數Java程序員來說,不需要了解網絡編程的底層細節,大家只需要有個概念,知道對于操作系統而言,底層是支持異步I/O通信的,只不過在很長一段時間Java并沒有提供異步I/O通信的類庫,導致很多原生的Java程序員對這塊兒比較陌生。當你了解了網絡編程的基礎知識后,理解Java的NIO類庫就會更加容易一些。

下一個小結我們重點講下I/O多路復用技術,因為Java NIO的核心類庫多路復用器Selector就是基于epoll的多路復用技術實現。

主站蜘蛛池模板: 兴安盟| 贵溪市| 栾川县| 丹巴县| 东海县| 平潭县| 新安县| 郯城县| 渭南市| 固阳县| 清新县| 微博| 凌海市| 康定县| 浮山县| 名山县| 张家界市| 巴中市| 宜川县| 稷山县| 介休市| 上栗县| 闵行区| 华安县| 辽阳市| 焉耆| 年辖:市辖区| 循化| 云南省| 观塘区| 田东县| 鹤峰县| 新田县| 济南市| 弥勒县| 乐平市| 雷州市| 前郭尔| 涡阳县| 扶绥县| 治县。|