<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Java NIO之理解I/O模型(二)

      前言

      上一篇文章講解了I/O模型的一些基本概念,包括同步與異步,阻塞與非阻塞,同步IO與異步IO,阻塞IO與非阻塞IO。這次一起來了解一下現有的幾種IO模型,以及高效IO的兩種設計模式,也都是屬于IO模型的基礎知識。

      UNIX下可用的五種I/O模型

      根據UNIX網絡編程對IO模型的分類,UNIX提供了5種IO模型,下面分別來介紹一下。

      阻塞I/O模型

      最常見的一種IO模型,之前介紹過,一個read操作是分兩個階段的,第一個階段是,等待數據準備就緒,第二個階段是將數據拷貝到調用這個IO的線程中。阻塞是發生在第一個階段的,當數據沒有準備好時,會一直阻塞用戶線程,當數據就緒后再將數據拷貝到線程中,并返回結果給用戶線程。

      大致過程如下圖。

       

      其實,大部分的socket接口都是典型的阻塞型。所謂阻塞型的接口是指系統調用(一般是IO接口)不返回調用結果并讓當前線程一直阻塞,只有當該系統調用獲得結果或者超時出錯時才返回。

      通過介紹了阻塞IO,我們很容易就會發現它的問題,那就是阻塞會是用戶線程無法進行任何運算和請求。一般我們的處理這種問題的情況是使用多線程,每個鏈接創建一個線程,或是使用線程池來管理線程,或許可以緩解部分壓力,但是不能解決所有問題。多線程模型可以方便高效的解決小規模的服務請求,但面對大規模的服務請求,多線程模型也會遇到瓶頸,可以用非阻塞接口來嘗試解決這個問題。

      非阻塞I/O模型

      非阻塞IO模型是這樣一個過程,當應用程序發起一個read操作時,并不會阻塞,而是立刻會收到一個結果。應用程序的線程發現返回結果是一個error時,它就知道數據還沒有準備好,于是它可以再次發送read操作。一旦數據準備好了,并且又再次收到了用戶線程的請求,那么它馬上就將數據拷貝到了用戶內存,然后返回。

      這樣的一個過程,其實是需要用戶線程不斷的去詢問系統是否準備好了數據,這樣就會一直占用CPU資源。但是這種模型是在只專門提供某種功能的系統才有。

      大致過程如下:

      多路I/O復用模型 

      在介紹多路復用I/O時就要先簡單說明一下,select函數和poll函數。

      select函數

      select函數允許進程指示內核等待多個事件中的任何一個事件發生,并且只在有一個或多個事件發生或經歷一段指定的時間后才喚醒它。

      • 舉個例子,我們可以調用select,告知內核僅在下列情況發生時才返回:
      • 集合 {1,4,5} 中的任何描述符準備好讀;
      • 集合 {2,7} 中的任何描述符準備好寫;
      • 集合 {1,4} 中的任何描述符有異常條件待處理;
      • 已經經歷10.2秒;

      也就是說,我們調用select告知內核對哪些描述符(讀、寫或異常條件)感興趣以及等待多長時間。

      poll函數

      poll函數起源于SVR3,最初局限于流設備。SVR4取消了這種限制,允許poll工作在任何描述符上。poll函數提供的功能與select函數類似,但是poll沒有最大文件描述符數量的限制。

      select函數和poll函數將就緒的文件描述符告訴進程后,如果進程沒有對其進行IO操作,那么下次調用select函數或者poll函數時會再次報告這些文件描述符, 所以他們一般不會丟失就緒的消息,這種方式稱為水平觸發(Level Triggered)。

      簡單的解了select函數和poll函數后,下面我們就繼續說多路I/O復用模型。多路IO復用模型就是調用select或poll函數,并且此模型的阻塞過程就是發生在調用這兩個函數中的,而不是發生在真正的的I/O系統調用上的,使用select或poll的好處在于可以用單個線程或進程,處理多個網絡連接的IO。整個過程就是select或poll函數會不斷的輪詢所負責的socket,當某個socket有數據到達了,就通知用戶線程或進程。

      大概調用如下:

       

      Java中的NIO實際上就是使用的多路IO復用模型,通過selector.select()去查詢每個通道是否有到達事件,如果沒有事件,則一直阻塞在那里,因此多路復用IO模型也會阻塞用戶線程,只不過線程是被select函數阻塞的而不是被scoket IO阻塞的。

      所以多路復用IO模型和非阻塞IO有類似之處,但是多路復用IO模型的效率是比非阻塞IO模型要高的,因為在非阻塞IO中,不斷的詢問scoket狀態的是通過用戶線程去進行的,而多路復用IO模型,輪詢每個scoket狀態是內核在進行的,這個效率是比用戶線程要高很多的。這樣也能看出來多路復用IO模型比較適合鏈接數比較多的情況。

      不過此模型也是存在問題的,由于多路復用IO模型是通過輪詢的方式來檢測是否有事件到達,并對到達的事件逐一響應,一旦事件響應體很大或是響應事件數量過多,就會消耗大量的時間去處理事件,從而影響整個過程的及時性。為了應對這種情況linux系統提供了epoll接口,但是除了linux的其他操作系統對epoll接口的支持又有很多差異,所以雖然epoll解決了事件檢測的時效性問題,但是在跨平臺能力上卻并不能得到很好的支持。

      信號驅動IO模型

      在信號驅動IO模型中,讓內核在數據報準備就緒時發送SIGIO信號通知用戶線程。

      整個過程如下:

      首先開啟套接字的信號驅動式IO功能,并通過sigaction系統調用安裝一個信號處理函數。該系統調用將立即返回,進程繼續工作,也就是說沒有被阻塞。當數據報準備好讀取時,內核就為該進程產生一個SIGIO信號。我們隨后就可以在信號處理函數中調用recvfrom讀取數據報,并通知用戶進程數據已經準備好了,可以讀取了。

      這種模型的優點在于等待數據報到達期間不會被阻塞,用戶進程可以繼續執行,只要等待來自信號處理函數的通知即可。

      異步IO模型

      異步IO模型的過程是這樣的,當用戶線程發起read操作時,告知內核啟動讀取數據操作,并讓內核在整個操作(包括將數據從內核復制到我們自己的緩沖區)完成后通知我們。這樣在內核執行讀取數據操作時,用戶線程可以繼續執行,當接收到內核在整個操作都完成的信號時,就可以直接去使用數據了。

      大致過程如下:

      在異步IO模型中,IO操作的兩個階段都不會阻塞用戶線程或進程,這兩個階段都是由內核完成的,然后發送一個信號告知用戶線程或進程操作已完成。異步IO模型與信號驅動IO模型的區別在于,信號驅動IO模型是由內核通知用戶線程何時啟動一個IO操作,而異步IO模型是由內核通知我們IO操作何時完成,異步IO模型中用戶線程并不需要進行實際的讀寫操作,只需要在內核操作完成后,接到讀取完成信號后,直接使用數據即可。

      異步IO是需要操作系統底層支持的,Linux從內核2.6版本才開始支持異步IO。在Java 7中就已經支持異步IO了。

      兩種高性能IO設計模式Reactor和Proactor

      Reactor模式

      Reactor的意思是反應器,字面意思就是立即反應。

      Reactor的工作方式:

      (1)應用程序注冊讀就緒事件和相關聯的事件處理器

      (2)Reactor阻塞等待內核事件通知

      (3)Reactor收到通知,然后分發可讀寫事件(讀寫準備就緒)到用戶事件處理函數

      (4)用戶讀取數據,并處理數據

      (5)事件處理器完成實際的讀操作,處理讀到的數據,注冊新的事件,然后返還控制權。

      大致過程是,每個應用程序宣布它對某個socket感興趣,然后就需要到Reactor中注冊感興趣事件以及相關的處理函數。當socket發現有事件到達時,就會按順序對每個事件進行處理(調用處理函數),當所有事件處理完成后,會繼續循環這整個操作。

      過程如下圖所示:

       

      從這個設計模式的處理過程中可以看出,多路IO復用模型就是使用的 Reactor模式,并且這種設計模式還是體現的同步IO。

      Proactor模式

      Proactor的意思是主動器,主動去完成相應的工作不影響主流程。

      Proactor模式的工作方式:

      (1)應用程序初始化一個異步讀取操作,然后注冊相應的事件處理器,此時事件處理器不關注讀取就緒事件,而是關注讀取完成事件,這是區別于Reactor的關鍵。

      (2)事件分離器等待讀取操作完成事件

      (3)在事件分離器等待讀取操作完成的時候,操作系統調用內核線程完成讀取操作,并將讀取的內容放入用戶傳遞過來的緩存區中。這也是區別于Reactor的一點,Proactor中,應用程序需要傳遞緩存區。

      (4)事件分離器捕獲到讀取完成事件后,激活應用程序注冊的事件處理器,事件處理器直接從緩存區讀取數據,而不需要進行實際的讀取操作。

      異步IO模型就是使用的Proactor模式。

       

       

       

       

      參考資料:

      《Unix網絡編程》

      http://www.rzrgm.cn/dolphin0520/p/3916526.html

      http://www.rzrgm.cn/findumars/p/6361627.html

      http://ifeve.com/io%E6%A8%A1%E5%9E%8B%E8%A7%A3%E6%83%91/

       

      posted @ 2019-09-23 01:01  紀莫  閱讀(900)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 精精国产xxx在线观看| 99久久精品久久久久久婷婷| 亚洲天堂一区二区三区三州| 男女真人国产牲交a做片野外| 乱码午夜-极品国产内射| 国产一区二区不卡在线| 艳妇乳肉豪妇荡乳在线观看| 亚洲精品一区二区三区大桥未久| 亚洲青青草视频在线播放| 日韩av一区二区高清不卡| 欧美老熟妇乱子伦牲交视频| 精品免费看国产一区二区| 91密桃精品国产91久久| 苍井空浴缸大战猛男120分钟| 久久精品一区二区三区av| 国产精品国产三级国快看| 亚洲欧美电影在线一区二区| 亚洲精品动漫免费二区| 精品国产乱码久久久久久婷婷 | 无套内谢少妇毛片在线| 欧美大bbbb流白水| 亚洲成av一区二区三区| 女高中生自慰污污网站| 亚洲日本中文字幕天天更新| 国产一区二区精品久久凹凸| 久久天天躁狠狠躁夜夜不卡| 国产亚洲一二三区精品| 少妇上班人妻精品偷人| 国产成人精品亚洲资源| 极品尤物被啪到呻吟喷水| 国产久久热这里只有精品| 欧美人与性动交α欧美精品| 人妻丰满熟妇av无码区| 蜜臀98精品国产免费观看| 自拍偷拍一区二区三区四| 在线日韩一区二区| 少妇撒尿一区二区在线视频| 中国少妇嫖妓BBWBBW| 亚洲区欧美区综合区自拍区| 久久精品免视看国产成人| 久青草视频在线免费观看|