在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

多路復用、同異步、BIO、NIO等知識點總結

FPGA之家 ? 來源:SoWhat1412 ? 作者:SoWhat1412 ? 2021-03-29 14:29 ? 次閱讀

承接上文的操作系統,關于IO會涉及到阻塞、非阻塞、多路復用、同步、異步、BIO、NIO、AIO等幾個知識點。知識點雖然不難但平常經常容易搞混,特此Mark下,與君共勉。

1 阻塞跟非阻塞

1.1 阻塞

0f65a7d2-8ecc-11eb-8b86-12bb97331649.png

阻塞IO

阻塞IO情況下,當用戶調用read后,用戶線程會被阻塞,等內核數據準備好并且數據從內核緩沖區拷貝到用戶態緩存區后read才會返回。可以看到是阻塞的兩個部分。

CPU把數據從磁盤讀到內核緩沖區。

CPU把數據從內核緩沖區拷貝到用戶緩沖區。

1.2 非阻塞

0f7f2662-8ecc-11eb-8b86-12bb97331649.png

非阻塞IO

非阻塞IO發出read請求后發現數據沒準備好,會繼續往下執行,此時應用程序會不斷輪詢polling內核詢問數據是否準備好,當數據沒有準備好時,內核立即返回EWOULDBLOCK錯誤。直到數據被拷貝到應用程序緩沖區,read請求才獲取到結果。并且你要注意!這里最后一次 read 調用獲取數據的過程,是一個同步的過程,是需要等待的過程。這里的同步指的是內核態的數據拷貝到用戶程序的緩存區這個過程。

1.3 IO多路復用

0ff84f92-8ecc-11eb-8b86-12bb97331649.png

IO多路復用

非阻塞情況下無可用數據時,應用程序每次輪詢內核看數據是否準備好了也耗費CPU,能否不讓它輪詢,當內核緩沖區數據準備好了,以事件通知當機制告知應用進程數據準備好了呢?應用進程在沒有收到數據準備好的事件通知信號時可以忙寫其他的工作。此時IO多路復用就派上用場了。

IO多路復用中文比較讓人頭大,IO多路復用的原文叫 I/O multiplexing,這里的 multiplexing 指的其實是在單個線程通過記錄跟蹤每一個Sock(I/O流)的狀態來同時管理多個I/O流。 發明它的目的是盡量多的提高服務器的吞吐能力。實現一個線程監控多個IO請求,哪個IO有請求就把數據從內核拷貝到進程緩沖區,拷貝期間是阻塞的!現在已經可以通過采用mmap地址映射的方法,達到內存共享效果,避免真復制,提高效率。

102591dc-8ecc-11eb-8b86-12bb97331649.png

IO多路復用

像select、poll、epoll 都是I/O多路復用的具體的實現。

1.3.1 select

select是第一版IO復用,提出后暴漏了很多問題。

select 會修改傳入的參數數組,這個對于一個需要調用很多次的函數,是非常不友好的。

select 如果任何一個sock(I/O stream)出現了數據,select 僅僅會返回,但不會告訴是那個sock上有數據,只能自己遍歷查找。

select 只能監視1024個鏈接。

select 不是線程安全的,如果你把一個sock加入到select, 然后突然另外一個線程發現這個sock不用,要收回,這個select 不支持的。

1.3.2 poll

poll 修復了 select 的很多問題。

poll 去掉了1024個鏈接的限制。

poll 從設計上來說不再修改傳入數組。

但是poll仍然不是線程安全的, 這就意味著不管服務器有多強悍,你也只能在一個線程里面處理一組 I/O 流。你當然可以拿多進程來配合了,不過然后你就有了多進程的各種問題。

1.3.3 epoll

epoll 可以說是 I/O 多路復用最新的一個實現,epoll 修復了poll 和select絕大部分問題, 比如:

epoll 現在是線程安全的。

epoll 現在不僅告訴你sock組里面數據,還會告訴你具體哪個sock有數據,你不用自己去找了。

epoll 內核態管理了各種IO文件描述符, 以前用戶態發送所有文件描述符到內核態,然后內核態負責篩選返回可用數組,現在epoll模式下所有文件描述符在內核態有存,查詢時不用傳文件描述符進去了。

1.3.4 三者對比

1064b894-8ecc-11eb-8b86-12bb97331649.png

對比圖

橫軸 Dead connections 是鏈接數的意思,叫這個名字只是它的測試工具叫deadcon。縱軸是每秒處理請求的數量,可看到epoll每秒處理請求的數量基本不會隨著鏈接變多而下降的。poll 和/dev/poll 就很慘了。但 epoll 有個致命的缺點是只有linux支持。

比如平常Nginx為何可以支持4W的QPS是因為它會使用目標平臺上面最高效的I/O多路復用模型。

1.4 異步IO

10b03198-8ecc-11eb-8b86-12bb97331649.png

異步IO

然后你會發現上面的提到過的操作都不是真正的異步,因為兩個階段總要等待會兒!而真正的異步 I/O 是內核數據準備好和數據從內核態拷貝到用戶態這兩個過程都不用等待。

很慶幸,Linux給我們準備了aio_read跟aio_write函數實現真實的異步,當用戶發起aio_read請求后就會自動返回。內核會自動將數據從內核緩沖區拷貝到用戶進程空間,應用進程啥都不用管。

2 同步跟異步

2.1 同步

同步跟異步的區別在于數據從內核空間拷貝到用戶空間是否由用戶線程完成,這里又分為同步阻塞跟同步非阻塞兩種。

同步阻塞:此時一個線程維護一個連接,該線程完成數據到讀寫跟處理到全部過程,數據讀寫時時線程是被阻塞的。

同步非阻塞:非阻塞的意思是用戶線程發出讀請求后,讀請求不會阻塞當前用戶線程,不過用戶線程還是要不斷的去主動判斷數據是否準備OK了。此時還是會阻塞等待內核復制數據到用戶進程。他與同步BIO區別是使用一個連接全程等待

我們以同步非阻塞為例,如下可看到,在將數據從內核拷貝到用戶空間這一過程,是由用戶線程阻塞完成的。

10fcf064-8ecc-11eb-8b86-12bb97331649.png

同步非阻塞

2.2 異步

對于異步來說,用戶進行讀或者寫后,將立刻返回,由內核去完成數據讀取以及拷貝工作,完成后通知用戶,并執行回調函數(用戶提供的callback),此時數據已從內核拷貝到用戶空間,用戶線程只需要對數據進行處理即可,不需要關注讀寫,用戶不需要等待內核對數據的復制操作,用戶在得到通知時數據已經被復制到用戶空間。我們以如下的真實異步非阻塞為例。

114594a4-8ecc-11eb-8b86-12bb97331649.png

異步IO

可發現,用戶在調用之后會立即返回,由內核完成數據的拷貝工作,并通知用戶線程,進行回調。

2.3 同步跟異步對比

同步關注的消息通信機制synchronous communication,在發出一個調用時,在沒有得到結果之前,該調用就不返回。但是一旦調用返回,就得到返回值了。換句話說,就是由調用者主動等待這個調用的結果。

異步關注消息通信機制asynchronous communication,調用在發出之后,這個調用就直接返回了,所以沒有返回結果。換句話說,當一個異步過程調用發出后,調用者不會立刻得到結果。而是在調用發出后,被調用者通過狀態、通知來通知調用者,或通過回調函數處理這個調用。

3 Java IO

在Java中,我們使用socket進行網絡通信,IO主要有三種模式,主要看內核支持哪些。

BIO:同步阻塞IO。

NIO:同步非阻塞IO。

AIO:異步非阻塞IO。

3.1 BIO

同步阻塞IO,每個客戶端的Socket連接請求,服務端都會對應有個處理線程與之對應,對于沒有分配到處理線程的連接就會被阻塞或者拒絕。相當于是一個連接一個線程。

117499ac-8ecc-11eb-8b86-12bb97331649.png

BIO

BIO特點:

使用一個獨立的線程維護一個socket連接,隨著連接數量的增多,對虛擬機造成一定壓力。

使用流來讀取數據,流是阻塞的,當沒有可讀/可寫數據時,線程等待,會造成資源的浪費。

3.1.1 BIO 樣例

常量:

public class Constant {

public static final String HOST = “127.0.0.1”;

public static final int PORT = 8080;

}

主類:

public class ClientMain {

public static void main(String[] args) {

//開啟服務

System.out.println(“開啟服務,監聽端口:” + Constant.PORT);

new Thread(new ServerThread()).start();

//建立一個socket客戶端,發起請求

System.out.println(“客戶端,請求連接,并發送數據”);

try {

Socket socket = new Socket(Constant.HOST,Constant.PORT);

//開啟新的線程處理socket連接

new Thread(new ClientProcessThread(socket)).start();

} catch (IOException e) {

e.printStackTrace();

}

}

}

服務端監聽線程:

// 開啟服務監聽線程,當收到連接請求后,開啟新的線程進行處理

public class ServerThread implements Runnable{

@Override

public void run() {

try {

ServerSocket serverSocket = new ServerSocket(Constant.PORT);

while (true){

Socket socket = serverSocket.accept();

new Thread(new ServerProcessThread(socket)).start();

//開啟新的線程進行連接請求的處理

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

服務端處理線程:

import java.io.*;

import java.net.Socket;

/**

* 服務端收到連接請求后,處理請求的線程,阻塞式IO

*/

public class ServerProcessThread implements Runnable {

private Socket socket;

public ServerProcessThread(Socket socket){

this.socket = socket;

}

@Override

public void run() {

//獲取客戶端的數據,并寫回

//等待響應

try {

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

String line = “”;

String requestStr = “”;

System.out.println(“來自客戶端的數據:”); // 讀取客戶端數據

while((line = bufferedReader.readLine()) != null){

requestStr += line;

System.out.println(line);

}

// 從服務端發給客戶端數據

Writer writer = new OutputStreamWriter(socket.getOutputStream());

writer.write(“data from server ” + requestStr + “

”);

writer.flush();

writer.close();

bufferedReader.close();

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

客戶端:

/**

* 維護客戶端socket連接的線程,阻塞式IO

*/

public class ClientProcessThread implements Runnable {

private Socket socket;

public ClientProcessThread(Socket socket){

this.socket = socket;

}

@Override

public void run() {

//寫數據,等待響應,輸出響應

String requestStr = “data from client

”;

try {

Writer writer = new OutputStreamWriter(socket.getOutputStream());

writer.write(requestStr);

writer.flush();

socket.shutdownOutput();

//等待響應

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

String line;

System.out.println(“來自服務端的響應:”);

while((line = bufferedReader.readLine()) != null){

System.out.println(line);

}

writer.close();

bufferedReader.close();

socket.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

輸出結果:

11b88f2c-8ecc-11eb-8b86-12bb97331649.png

3.2 NIO

同步非阻塞IO之NIO:服務器端保存一個Socket連接列表,然后對這個列表進行輪詢,如果發現某個Socket端口上有數據可讀時說明讀就緒,則調用該socket連接的相應讀操作。如果發現某個 Socket端口上有數據可寫時說明寫就緒,則調用該socket連接的相應寫操作。如果某個端口的Socket連接已經中斷,則調用相應的析構方法關閉該端口。這樣能充分利用服務器資源,效率得到了很大提高,在進行IO操作請求時候再用個線程去處理,是一個請求一個線程。Java中使用Selector、Channel、Buffer來實現上述效果。

12096712-8ecc-11eb-8b86-12bb97331649.png

NIO

每個線程中包含一個Selector對象,它相當于一個通道管理器,可以實現在一個線程中處理多個通道的目的,減少線程的創建數量。遠程連接對應一個channel,數據的讀寫通過buffer均在同一個channel中完成,并且數據的讀寫是非阻塞的。通道創建后需要注冊在selector中,同時需要為該通道注冊感興趣事件(客戶端連接服務端事件、服務端接收客戶端連接事件、讀事件、寫事件),selector線程需要采用輪訓的方式調用selector的select函數,直到所有注冊通道中有興趣的事件發生,則返回,否則一直阻塞。而后循環處理所有就緒的感興趣事件。以上步驟解決BIO的兩個瓶頸:

不必對每個連接分別創建線程。

數據讀寫非阻塞。

下面對以下三個概念做一個簡單介紹,Java NIO由以下三個核心部分組成:

selector:Selector 允許單線程處理多個Channel。如果你的應用打開了多個連接(通道),但每個連接的流量都很低,使用Selector就會很方便。要使用Selector,得向Selector注冊Channel,然后調用他的select方法,這個方法會一直阻塞到某個注冊的通道有事件就緒。一旦這個方法返回,線程就可以處理這些事件,事件的例子入有新連接接進來,數據接收等。

Channel:基本上所有的IO在NIO中都從一個Channel開始。Channel有點像流,數據可以從channel讀到buffer,也可以從buffer寫到channel。

Buffer:緩沖區本質上是一個可以讀寫數據的內存塊,可以理解成是一個容器對象(含數組),該對象提供了一組方法,可以更輕松的使用內存塊,緩沖區對象內置了一些機制,能夠跟蹤和記錄緩沖區的狀態變換情況,Channel提供從文件,網絡讀取數據的渠道,但是讀取或者寫入的數據都必須經由Buffer。

channel和buffer有好幾種類型。下面是Java NIO中的一些主要channel的實現:

FileChannel

DatagramChannel

SocketChannel

ServerSocketChannel

正如你所看到的,這些通道涵蓋了UDP和TCP網絡IO,以及文件IO。以下是Java NIO里關鍵的buffer實現:

ByteBuffer

CharBuffer

FloatBuffer

IntBuffer

LongBuffer

ShortBuffer

在微服務階段,一個請求可能涉及到多個不同服務之間的跨服務器調用,如果你想實現高性能的PRC框架來進行數據傳輸,那就可以基于Java NIO做個支持長連接、自定義協議、高并發的框架,比如Netty。Netty本身就是一個基于NIO的網絡框架, 封裝了Java NIO那些復雜的底層細節,給你提供簡單好用的抽象概念來編程。比如Dubbo底層就是用的Netty。

121a8e98-8ecc-11eb-8b86-12bb97331649.png

Netty通訊模式

3.3 AIO

AIO是異步非阻塞IO,相比NIO更進一步,進程讀取數據時只負責發送跟接收指令,數據的準備工作完全由操作系統來處理。

原文標題:阻塞、非阻塞、多路復用、同步、異步、BIO、NIO、AIO 一鍋端

文章出處:【微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。

責任編輯:haq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 同步
    +關注

    關注

    0

    文章

    89

    瀏覽量

    19253
  • 異步
    +關注

    關注

    0

    文章

    62

    瀏覽量

    18107
  • AIO
    AIO
    +關注

    關注

    1

    文章

    62

    瀏覽量

    10025

原文標題:阻塞、非阻塞、多路復用、同步、異步、BIO、NIO、AIO 一鍋端

文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    多路復用模擬輸入應用中使用ADS8411

    電子發燒友網站提供《在多路復用模擬輸入應用中使用ADS8411.pdf》資料免費下載
    發表于 10-22 09:32 ?0次下載
    在<b class='flag-5'>多路復用</b>模擬輸入應用中使用ADS8411

    AM17xx引腳多路復用實用程序

    電子發燒友網站提供《AM17xx引腳多路復用實用程序.pdf》資料免費下載
    發表于 10-14 10:22 ?0次下載
    AM17xx引腳<b class='flag-5'>多路復用</b>實用程序

    多路復用器應用中的防護

    電子發燒友網站提供《多路復用器應用中的防護.pdf》資料免費下載
    發表于 09-21 10:47 ?0次下載
    <b class='flag-5'>多路復用</b>器應用中的防護

    基于帶寬的無源多路復用器>Ron

    電子發燒友網站提供《基于帶寬的無源多路復用器>Ron.pdf》資料免費下載
    發表于 09-21 10:46 ?0次下載
    基于帶寬的無源<b class='flag-5'>多路復用</b>器>Ron

    電源多路復用器基礎知識

    電子發燒友網站提供《電源多路復用器基礎知識.pdf》資料免費下載
    發表于 09-21 10:21 ?0次下載
    電源<b class='flag-5'>多路復用</b>器基礎<b class='flag-5'>知識</b>

    如何使用多路復用器處理高壓共模應用

    電子發燒友網站提供《如何使用多路復用器處理高壓共模應用.pdf》資料免費下載
    發表于 09-11 11:34 ?0次下載
    如何使用<b class='flag-5'>多路復用</b>器處理高壓共模應用

    多路復用器將取代繼電器應用說明

    電子發燒友網站提供《多路復用器將取代繼電器應用說明.pdf》資料免費下載
    發表于 09-11 10:05 ?0次下載
    <b class='flag-5'>多路復用</b>器將取代繼電器應用說明

    電源多路復用器電路設計指南

    電子發燒友網站提供《電源多路復用器電路設計指南.pdf》資料免費下載
    發表于 07-13 09:33 ?0次下載

    什么是多路復用器?它有哪些作用和應用?

    在現代通信與數據處理領域,多路復用器(Multiplexer,簡稱MUX)作為一種關鍵設備,發揮著不可替代的作用。它能夠將多個輸入信號選擇性地合并到一個輸出信號中,從而實現了對通信信道的高效利用
    的頭像 發表于 05-23 16:38 ?4370次閱讀

    模擬電子技術知識點問題總結概覽

    給大家分享模擬電子技術知識點問題總結。
    的頭像 發表于 05-08 15:16 ?1249次閱讀
    模擬電子技術<b class='flag-5'>知識點</b>問題<b class='flag-5'>總結</b>概覽

    頻分多路復用和時分多路復用的區別有哪些

    頻分多路復用(FDM)和時分多路復用(TDM)是兩種主要的多路復用技術,它們在通信系統中扮演著至關重要的角色。
    的頭像 發表于 05-07 15:24 ?3238次閱讀

    多路復用技術主要有幾種類型?它們各有什么特點?

    多路復用技術主要有幾種類型?它們各有什么特點? 多路復用技術主要有以下幾種類型:進程多路復用、I/O多路復用、信號驅動I/O和異步I/O。每
    的頭像 發表于 03-28 15:36 ?3188次閱讀

    一文詳解多路復用的類型

    多路復用最初是在電話中發展起來的。多個信號被組合在一起,通過一根電纜發送。
    的頭像 發表于 03-05 15:44 ?3752次閱讀
    一文詳解<b class='flag-5'>多路復用</b>的類型

    多路復用的原理 為什么要多路復用?多路復用技術的應用

    在計算機網絡中,多路復用是一種重要的通信技術,它允許多個信號通過同一個通信信道進行傳輸。
    的頭像 發表于 03-05 15:09 ?3150次閱讀
    <b class='flag-5'>多路復用</b>的原理 為什么要<b class='flag-5'>多路復用</b>?<b class='flag-5'>多路復用</b>技術的應用

    頻分多路復用的原理 頻分多路復用方式的分類

    頻分多路復用(Frequency-division multiplexing,FDM),是指載波帶寬被劃分為多種不同頻帶的子信道,每個子信道可以并行傳送一路信號的一種多路復用技術。
    的頭像 發表于 03-05 14:10 ?1709次閱讀
    頻分<b class='flag-5'>多路復用</b>的原理 頻分<b class='flag-5'>多路復用</b>方式的分類
    主站蜘蛛池模板: 免费欧洲美女与动zooz | 成人网男女啪啪免费网站 | 午夜精品久久久 | 午夜在线观看免费高清在线播放 | 亚洲人成网i8禁止 | 国产xxxxxx久色视频在 | 一区二区三区视频在线 | 日日夜夜2017 | 四虎最新网址 | 天天草天天草 | 91在线操 | 黄黄网| 特级做a爰片毛片免费看一区 | 西西人体44rt高清午夜 | 日本不卡在线视频高清免费 | 四虎影视永久在线 yin56xyz | 久久久久国产一级毛片高清片 | 久久99久久精品国产只有 | 一区二区高清在线 | 欧美又黄又嫩大片a级 | 天天爱天天插 | 亚洲xx网站 | 卡2卡三卡四卡精品公司 | 免费观看一级特黄三大片视频 | 77788色淫网站免费观看 | 三级黄色片免费观看 | 亚洲综合五月天婷 | 精品在线一区二区 | 四虎影永久在线观看精品 | 美女一级一级毛片 | 成人欧美精品大91在线 | 操农村妇女| 亚洲韩国日本欧美一区二区三区 | 日本大片免费播放网站 | 天天干夜夜怕 | 欧美特黄特色aaa大片免费看 | 亚洲精品美女视频 | 久久视频免费 | 婷色 | 999久久久国产精品 999久久久免费精品国产牛牛 | 色狠狠狠狠综合影视 |