欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

不同網(wǎng)絡(luò)I/O模型的原理分析

 更新時(shí)間:2025年06月30日 09:07:48   作者:找不到、了  
這篇文章主要介紹了不同網(wǎng)絡(luò)I/O模型的原理分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

在網(wǎng)絡(luò)I/O之中,I/O操作往往會(huì)涉及到兩個(gè)系統(tǒng)對(duì)象,一個(gè)是用戶空間調(diào)用I/O的進(jìn)程或者線程,另一個(gè)是內(nèi)核空間的內(nèi)核系統(tǒng),當(dāng)發(fā)生I/O操作時(shí),會(huì)經(jīng)歷以下兩個(gè)階段:

1. 等待數(shù)據(jù)準(zhǔn)備就緒

2. 將數(shù)據(jù)從內(nèi)核拷貝到進(jìn)程或線程中

因?yàn)樵谝陨蟽蓚€(gè)階段上各有不同的情況,所以出現(xiàn)了多種I/O模型。

如下圖所示:

1、I/O的介紹

I/O 操作(Input/Output Operation)指的是計(jì)算機(jī)系統(tǒng)中與外部環(huán)境(如網(wǎng)絡(luò)、磁盤、鍵盤、顯示器等)進(jìn)行數(shù)據(jù)交換的過程。

1.1、I/O 操作分類

1.網(wǎng)絡(luò)輸入(接收數(shù)據(jù)):

如 recv() 或 read() 函數(shù),用于從網(wǎng)絡(luò)連接中讀取數(shù)據(jù)。

2.網(wǎng)絡(luò)輸出(發(fā)送數(shù)據(jù)):

如 send() 或 write() 函數(shù),用于向網(wǎng)絡(luò)連接發(fā)送數(shù)據(jù)。

3.網(wǎng)絡(luò)連接管理:

如 accept() 函數(shù),用于接受來自客戶端的連接請(qǐng)求。

4.網(wǎng)絡(luò)監(jiān)聽:

如 listen() 函數(shù),用于監(jiān)聽進(jìn)入的連接請(qǐng)求。

1.2、I/O操作流程階段

通常用戶進(jìn)程中的一個(gè)完整I/O分為兩個(gè)階段:

用戶進(jìn)程空間→內(nèi)核空間 ,內(nèi)核空間→設(shè)備空間;

整體模型圖所示:

1.3、I/O分類

I/O分為內(nèi)存I/O、網(wǎng)絡(luò)I/O和磁盤I/O三種。

1、內(nèi)存I/O

涉及直接與計(jì)算機(jī)內(nèi)存進(jìn)行數(shù)據(jù)交換,如讀取和寫入內(nèi)存中的數(shù)據(jù)。

2、網(wǎng)絡(luò)I/O

涉及通過網(wǎng)絡(luò)接口進(jìn)行的數(shù)據(jù)交換,例如從服務(wù)器下載文件或向服務(wù)器發(fā)送請(qǐng)求。

3、磁盤I/O

涉及與存儲(chǔ)設(shè)備(如硬盤驅(qū)動(dòng)器或固態(tài)硬盤)進(jìn)行數(shù)據(jù)交換,例如讀取和寫入磁盤上的文件。

Linux中進(jìn)程無法直接操作I/O設(shè)備,其必須通過系統(tǒng)調(diào)用請(qǐng)求內(nèi)核來協(xié)助完成I/O操作。 內(nèi)核會(huì)為每個(gè)I/O設(shè)備(例如硬盤、網(wǎng)絡(luò)接口)維護(hù)一個(gè)緩沖區(qū),緩沖區(qū)是內(nèi)存中的一塊區(qū)域,用于臨時(shí)存儲(chǔ)數(shù)據(jù),以提高I/O操作的效率。

對(duì)于一個(gè)輸入操作來說,進(jìn)程I/O系統(tǒng)調(diào)用(如 read())讀取數(shù)據(jù)時(shí),它會(huì)先看為該設(shè)備維護(hù)的緩沖區(qū),看看是否已經(jīng)有待處理的數(shù)據(jù)。沒有的話再到設(shè)備(比如網(wǎng)卡設(shè)備)中讀?。ㄒ?yàn)樵O(shè)備I/O一般速度較慢,需要等待)。

如果緩沖區(qū)中沒有數(shù)據(jù),內(nèi)核會(huì)發(fā)起設(shè)備I/O操作,從設(shè)備(例如網(wǎng)絡(luò)接口卡、磁盤等)中讀取數(shù)據(jù)。由于設(shè)備I/O操作通常較慢,需要時(shí)間來完成,內(nèi)核會(huì)先等待數(shù)據(jù)到達(dá)設(shè)備緩沖區(qū),再進(jìn)行處理。

如下圖所示:

所以,對(duì)于一個(gè)網(wǎng)絡(luò)輸入操作通常包括兩個(gè)不同階段:

1、等待網(wǎng)絡(luò)數(shù)據(jù)到達(dá)網(wǎng)卡,把數(shù)據(jù)從網(wǎng)卡讀取到內(nèi)核緩沖區(qū),準(zhǔn)備好數(shù)據(jù)。

2、從內(nèi)核緩沖區(qū)復(fù)制數(shù)據(jù)到用戶進(jìn)程空間。

注意:

  • 如果緩沖區(qū)中有數(shù)據(jù):內(nèi)核會(huì)直接從緩沖區(qū)中獲取數(shù)據(jù),并將這些數(shù)據(jù)復(fù)制到用戶進(jìn)程的地址空間。
  • 這種情況通常較快,因?yàn)閿?shù)據(jù)已經(jīng)在內(nèi)核空間中,可以快速傳遞給用戶進(jìn)程。

小結(jié)

  • Socket:在Linux中,socket是一種用于網(wǎng)絡(luò)通信的抽象接口,提供了數(shù)據(jù)傳輸?shù)臋C(jī)制。socket可以被看作是一個(gè)端點(diǎn),允許進(jìn)程通過它進(jìn)行數(shù)據(jù)的發(fā)送和接收。
  • 流的抽象:在Linux中,socket被視為一種流(例如TCP流),它允許進(jìn)程以流式方式讀寫數(shù)據(jù)。對(duì)于TCP協(xié)議來說,數(shù)據(jù)流是有序的、可靠的。

流的抽象可以理解為像流水一樣的數(shù)據(jù)傳輸方式,強(qiáng)調(diào)了數(shù)據(jù)傳輸?shù)倪B續(xù)性和按序性,而不關(guān)心數(shù)據(jù)的具體格式。當(dāng)使用socket進(jìn)行網(wǎng)絡(luò)通信時(shí),網(wǎng)絡(luò)層和傳輸層只處理數(shù)據(jù)的流動(dòng),應(yīng)用層則負(fù)責(zé)數(shù)據(jù)的解析和處理。

I/O操作:對(duì)socket的讀寫操作實(shí)際上是對(duì)網(wǎng)絡(luò)流的操作。當(dāng)進(jìn)程發(fā)起對(duì)socket的讀取操作時(shí),內(nèi)核會(huì)檢查緩沖區(qū)是否有數(shù)據(jù)可用。如果有,數(shù)據(jù)會(huì)被傳遞給進(jìn)程;如果沒有,進(jìn)程會(huì)被阻塞直到數(shù)據(jù)到達(dá)。

2、同步I/O

2.1、阻塞I/O

也稱為BIO(Blocking I/O)。

1.核心原理

  • 阻塞式 I/O:每個(gè)連接由一個(gè)線程處理,線程在讀寫數(shù)據(jù)時(shí)會(huì)阻塞,直到數(shù)據(jù)準(zhǔn)備好。
  • 典型模型一請(qǐng)求一線程(One Thread Per Connection)。
  • 底層機(jī)制:基于InputStreamOutputStream的阻塞操作。

整體原理圖如下所示:

流程如下:

  • 第一步通常涉及等待數(shù)據(jù)從網(wǎng)絡(luò)中到達(dá),當(dāng)所有等待分組到達(dá)時(shí),它被復(fù)制到內(nèi)核中的某個(gè)緩沖區(qū)。
  • 第二步是把數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到應(yīng)用程序緩沖區(qū)。

在Linux中,默認(rèn)情況下,阻塞I/O的所有套接字都是阻塞的。

2.代碼示例

// BIO 服務(wù)器示例
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
Socket socket = serverSocket.accept(); // 阻塞,等待連接
new Thread(() -> {
InputStream input = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = input.read(buffer); // 阻塞,等待數(shù)據(jù)
System.out.println(new String(buffer, 0, len));
}).start();
}

3.優(yōu)點(diǎn)

  • 實(shí)現(xiàn)簡(jiǎn)單:代碼結(jié)構(gòu)直觀,適合小規(guī)模應(yīng)用。
  • 調(diào)試方便:線程模型清晰,便于排查問題。

4.缺點(diǎn)

  • 性能瓶頸:高并發(fā)時(shí),線程數(shù)激增,占用大量?jī)?nèi)存和 CPU,容易導(dǎo)致資源耗盡。
  • 擴(kuò)展性差:不適合處理成千上萬的并發(fā)連接。

5.適用場(chǎng)景

  • 低并發(fā)場(chǎng)景:如小型客戶端/服務(wù)器應(yīng)用(如命令行工具、簡(jiǎn)單的 HTTP 服務(wù))。
  • 簡(jiǎn)單協(xié)議處理:對(duì)性能要求不高的場(chǎng)景。

2.2、非阻塞I/O

允許應(yīng)用程序在數(shù)據(jù)未準(zhǔn)備好時(shí)不必等待,可以繼續(xù)執(zhí)行其他任務(wù)。

(Non-blocking I/O)模型如下所示:

流程如下:

非阻塞的recvform系統(tǒng)調(diào)用之后,進(jìn)程并沒有被阻塞,內(nèi)核馬上返回給進(jìn)程,如果數(shù)據(jù)還沒準(zhǔn)備好,此時(shí)會(huì)返回一個(gè)error(EAGAIN或EWOULDBLOCK)。

進(jìn)程在返回之后,可以先處理其他的業(yè)務(wù)邏輯,稍后再發(fā)起recvform系統(tǒng)調(diào)用。 采用輪詢的方式檢查內(nèi)核數(shù)據(jù),直到數(shù)據(jù)準(zhǔn)備好。再拷貝數(shù)據(jù)到進(jìn)程,進(jìn)行數(shù)據(jù)處理。

在Linux下,可以通過設(shè)置套接字選項(xiàng)使其變?yōu)榉亲枞?/strong>

總結(jié):

可以看到前三次調(diào)用recvfrom請(qǐng)求時(shí),并沒有數(shù)據(jù)返回,內(nèi)核返回errno(EWOULDBLOCK),并不會(huì)阻塞進(jìn)程。 當(dāng)?shù)谒拇握{(diào)用recvfrom時(shí),數(shù)據(jù)已經(jīng)準(zhǔn)備好了,于是將它從內(nèi)核空間拷貝到程序空間,處理數(shù)據(jù)。

??注意:但是將數(shù)據(jù)從內(nèi)核拷貝到用戶空間,這個(gè)階段阻塞。

2.3、I/O復(fù)用

多路監(jiān)控:使用select、poll或epoll等系統(tǒng)調(diào)用來監(jiān)控多個(gè)I/O流。當(dāng)其中一個(gè)I/O流有數(shù)據(jù)可讀或可寫時(shí),系統(tǒng)調(diào)用返回。適用于在單個(gè)線程內(nèi)管理多個(gè)連接。

(I/O Multiplexing)模型如下所示:

流程如下:

I/O多路復(fù)用的好處在于單個(gè)進(jìn)程就可以同時(shí)處理多個(gè)網(wǎng)絡(luò)連接的I/O。

它的基本原理是不再由應(yīng)用程序自己監(jiān)視連接,而由內(nèi)核替應(yīng)用程序監(jiān)視文件描述符。通過 select、poll、epoll 等機(jī)制,允許一個(gè)進(jìn)程同時(shí)監(jiān)視多個(gè)文件描述符,當(dāng)某個(gè)文件描述符就緒時(shí)再進(jìn)行 IO 操作。這種模型下,程序可以同時(shí)處理多個(gè)連接,提高了并發(fā)處理能力。

示例:

以select函數(shù)為例,當(dāng)用戶進(jìn)程調(diào)用了select,那么整個(gè)進(jìn)程會(huì)被阻塞,而同時(shí),kernel會(huì)“監(jiān)視”所有select負(fù)責(zé)的socket,當(dāng)任何一個(gè)socket中的數(shù)據(jù)準(zhǔn)備好,select就會(huì)返回。 這個(gè)時(shí)候用戶進(jìn)程再調(diào)用read操作,將數(shù)據(jù)從內(nèi)核拷貝到用戶進(jìn)程。

注意:

  • 當(dāng)客戶處理多個(gè)描述符時(shí),必須使用I/O復(fù)用;
  • 如果一個(gè)TCP服務(wù)器既要處理監(jiān)聽套接字,又要處理已連接的套接字,一般就要使用I/O復(fù)用;
  • 如果一個(gè)服務(wù)器既要處理TCP,又要處理UDP,一般就要使用I/O復(fù)用。
  • 如果一個(gè)服務(wù)器要處理多個(gè)協(xié)議或多個(gè)服務(wù),一般就需要使用I/O復(fù)用。

2.4、信號(hào)驅(qū)動(dòng)式I/O

該模型允許socket進(jìn)行信號(hào)驅(qū)動(dòng)I/O,并注冊(cè)一個(gè)信號(hào)處理函數(shù),進(jìn)程繼續(xù)運(yùn)行并不阻塞。當(dāng)數(shù)據(jù)準(zhǔn)備好時(shí),進(jìn)程會(huì)收到一個(gè)SIGIO信號(hào),可以在信號(hào)處理函數(shù)中調(diào)用I/O操作函數(shù)處理數(shù)據(jù)。

模型如下圖所示:

注意:

雖然信號(hào)驅(qū)動(dòng)IO在注冊(cè)完信號(hào)處理函數(shù)以后,就可以做其他事情了。但是第二階段拷貝數(shù)據(jù)的過程當(dāng)中進(jìn)程依然是被阻塞的。

3、異步I/O

異步I/O的工作機(jī)制:告知內(nèi)核啟動(dòng)某個(gè)操作,并讓內(nèi)核在整個(gè)操作(包括將數(shù)據(jù)從內(nèi)核復(fù)制到我們自己的緩沖區(qū))完成后通知我們。

異步I/O與信號(hào)驅(qū)動(dòng)I/O模型區(qū)別在于:

信號(hào)驅(qū)動(dòng)式I/O是有內(nèi)核通知我們何時(shí)可以啟動(dòng)一個(gè)I/O操作,而異步I/O模型是由內(nèi)核通知我們I/O操作何時(shí)完成。

模型如下圖所示:

異步I/O不是按順序執(zhí)行。用戶進(jìn)程進(jìn)行aio_read系統(tǒng)調(diào)用之后,就可以去處理其他邏輯了,無論內(nèi)核數(shù)據(jù)是否準(zhǔn)備好,都會(huì)直接返回給用戶進(jìn)程,不會(huì)對(duì)進(jìn)程造成阻塞。

這是因?yàn)閍io_read只向內(nèi)核遞交申請(qǐng),并不關(guān)心有沒有數(shù)據(jù)。 等到數(shù)據(jù)準(zhǔn)備好了,內(nèi)核直接復(fù)制數(shù)據(jù)到進(jìn)程空間,然后內(nèi)核向進(jìn)程發(fā)送通知,此時(shí)數(shù)據(jù)已經(jīng)在用戶空間了,可以對(duì)數(shù)據(jù)進(jìn)行處理。

總結(jié)

同步I/O和異步I/O的比較:

  • 同步I/O:導(dǎo)致請(qǐng)求進(jìn)程阻塞,直到I/O操作完成;
  • 異步I/O:不導(dǎo)致請(qǐng)求進(jìn)程阻塞;

簡(jiǎn)單的講:就是是否參與了I/O操作;

前四種I/O模型——阻塞式I/O模型、非阻塞式I/O模型、I/O復(fù)用(多路轉(zhuǎn)接)和信號(hào)驅(qū)動(dòng)式I/O模型都是同步I/O,第二步從數(shù)據(jù)從內(nèi)核態(tài)copy到用戶態(tài)的I/O操作(recvfrom)將進(jìn)程阻塞。

只有異步I/O模型是異步I/O。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 解決IDEA報(bào)錯(cuò)Failed?to?start?bean‘documentationPluginsBootstrapper‘問題

    解決IDEA報(bào)錯(cuò)Failed?to?start?bean‘documentationPluginsBootstra

    這篇文章主要介紹了解決IDEA報(bào)錯(cuò)Failed?to?start?bean‘documentationPluginsBootstrapper‘問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • java線程之用Thread類創(chuàng)建線程的方法

    java線程之用Thread類創(chuàng)建線程的方法

    本篇文章介紹了,Thread類創(chuàng)建線程的方法。需要的朋友參考下
    2013-05-05
  • 教你使用eclipse?搭建Swt?環(huán)境的全過程

    教你使用eclipse?搭建Swt?環(huán)境的全過程

    本文給大家分享使用eclipse?搭建Swt?環(huán)境的全過程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • 輕松掌握J(rèn)ava橋接模式

    輕松掌握J(rèn)ava橋接模式

    這篇文章主要幫助大家輕松掌握J(rèn)ava橋接模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Spring jdbc具名參數(shù)使用方法詳解

    Spring jdbc具名參數(shù)使用方法詳解

    這篇文章主要介紹了Spring jdbc具名參數(shù)使用方法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • spring validation多層對(duì)象校驗(yàn)教程

    spring validation多層對(duì)象校驗(yàn)教程

    這篇文章主要介紹了spring validation多層對(duì)象校驗(yàn)教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java異常(Exception)處理以及常見異??偨Y(jié)

    Java異常(Exception)處理以及常見異??偨Y(jié)

    在《Java編程思想》中這樣定義異常,阻止當(dāng)前方法或作用域繼續(xù)執(zhí)行的問題,雖然java中有異常處理機(jī)制,但是要明確一點(diǎn),決不應(yīng)該用"正常"的態(tài)度來看待異常,這篇文章主要給大家介紹了關(guān)于Java異常(Exception)處理以及常見異常的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • 總結(jié)一下Java回調(diào)機(jī)制的相關(guān)知識(shí)

    總結(jié)一下Java回調(diào)機(jī)制的相關(guān)知識(shí)

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識(shí),文章圍繞著Java回調(diào)機(jī)制展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Java模擬實(shí)現(xiàn)撲克牌洗牌和發(fā)牌的示例代碼

    Java模擬實(shí)現(xiàn)撲克牌洗牌和發(fā)牌的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何利用Java模擬實(shí)現(xiàn)撲克牌洗牌和發(fā)牌的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下
    2022-09-09
  • Java如何設(shè)置過期時(shí)間的map的幾種方法

    Java如何設(shè)置過期時(shí)間的map的幾種方法

    本文主要介紹了Java如何設(shè)置過期時(shí)間的map的幾種方法,常見的解決方法有:ExpiringMap、LoadingCache及基于HashMap的封裝三種,下面就詳細(xì)的介紹一下,感興趣的可以了解下
    2022-03-03

最新評(píng)論