0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

網(wǎng)絡(luò)IO模型:阻塞與非阻塞

麥辣雞腿堡 ? 來(lái)源:盼盼編程 ? 作者:盼盼編程 ? 2023-10-08 17:16 ? 次閱讀

阻塞 IO 模型

Linux ,默認(rèn)情況下所有的 socket 都是阻塞的,一個(gè)典型的讀操作流程如圖所示。

阻塞和非阻塞的概念描述的是用戶(hù)線程調(diào)用內(nèi)核 IO 操作的方式:阻塞是指 IO 操作需要徹底完成后才返回到用戶(hù)空間;而非阻塞是指 IO操作被調(diào)用后立即返回給用戶(hù)一個(gè)狀態(tài)值,不需要等到 IO 操作徹底完成。

當(dāng)應(yīng)用進(jìn)程調(diào)用了 recvfrom 這個(gè)系統(tǒng)調(diào)用后,系統(tǒng)內(nèi)核就開(kāi)始了 IO 的第一個(gè)階段 :準(zhǔn)備數(shù)據(jù)。

對(duì)于網(wǎng)絡(luò) IO 來(lái)說(shuō),很多時(shí)候數(shù)據(jù)在一開(kāi)始還沒(méi)到達(dá)時(shí),系統(tǒng)內(nèi)核就要等待足夠的數(shù)據(jù)到來(lái)。而在用戶(hù)進(jìn)程這邊,整個(gè)進(jìn)程會(huì)被阻塞。

當(dāng)系統(tǒng)內(nèi)核一直等到數(shù)據(jù)準(zhǔn)備好了,它就會(huì)將數(shù)據(jù)從系統(tǒng)內(nèi)核中拷貝到用戶(hù)內(nèi)存中,然后系統(tǒng)內(nèi)核返回結(jié)果,用戶(hù)進(jìn)程才解除阻塞的狀態(tài),重新運(yùn)行起來(lái)。所以,阻塞IO 模型的特點(diǎn)就是 IO 執(zhí)行的兩個(gè)階段都被阻塞了。

大部分的 socke接口都是阻塞型的。所謂阻塞型接口是指系統(tǒng)調(diào)用時(shí)卻不返回調(diào)用結(jié)果,并讓當(dāng)前線程一直處于阻塞狀態(tài),只有當(dāng)該系統(tǒng)調(diào)用獲得結(jié)果或者超時(shí)出錯(cuò)時(shí)才返回結(jié)果。

實(shí)際上,除非特別指定,幾乎所有的 IO 接口都阻塞型的。這給網(wǎng)絡(luò)編程帶來(lái)了一個(gè)很大的問(wèn)題,如在調(diào)用 send的同時(shí),線程處于阻塞狀態(tài),則在此期間,線程將無(wú)法執(zhí)行任何運(yùn)算或響應(yīng)任何網(wǎng)絡(luò)請(qǐng)求。

非阻塞 IO 模型

在Linux 下,可以通過(guò)設(shè)置 socket IO 變?yōu)榉亲枞麪顟B(tài)。當(dāng)一個(gè)非阻塞的 socket執(zhí)行 read 操作時(shí),流程如圖:

圖片

當(dāng)用戶(hù)進(jìn)程發(fā)出 read 操作時(shí),如果內(nèi)核中的數(shù)據(jù)還沒(méi)有準(zhǔn)備好,那么它并不會(huì) block 用戶(hù)進(jìn)程,而是立刻返回一個(gè)錯(cuò)誤。

從用戶(hù)進(jìn)程角度講,它發(fā)起 read 操作后,并不需要等待,而是馬上就得到了一個(gè)結(jié)果當(dāng)用戶(hù)進(jìn)程判斷結(jié)果是一個(gè)錯(cuò)誤時(shí),它就知道數(shù)據(jù)還沒(méi)有準(zhǔn)備好,于是它可以再次發(fā)送 read 操作。

一旦內(nèi)核中的數(shù)據(jù)準(zhǔn)備好了,并且又再次收到了用戶(hù)進(jìn)程的系統(tǒng)調(diào)用,那么它馬上就將數(shù)據(jù)復(fù)制到了用戶(hù)內(nèi)存中,然后返回正確的返回值。

所以,在非阻塞式 IO 中,用戶(hù)進(jìn)程其實(shí)需要不斷地主動(dòng)詢(xún)問(wèn) kernel數(shù)據(jù)是否準(zhǔn)備好。非阻塞的接口相比于阻塞型接口的顯著差異在于被調(diào)用之后立即返回,使用如下的函數(shù)可以將某句柄歸設(shè)為非阻塞狀態(tài):fcntl( fd , F_SETFL, O_NONBLOCK);

在非阻塞狀態(tài)下,recv 接口在被調(diào)用后立即返回,返回值代表了不同的含義,如下所述。

recv 返回值大于 0,表示接收數(shù)據(jù)完畢,返回值即是接收到的字節(jié)數(shù)。

recv 返回 0,表示連接已經(jīng)正常斷開(kāi)。

recv 返回 -1 ,且 errno 等于 EAGAIN ,表示 recv 操作還沒(méi)執(zhí)行完成。

recv 返回 -1,且 errno 不等于 EAGAIN ,表示 recv 操作遇到系統(tǒng)錯(cuò)誤 errno。

可以看到服務(wù)器線程可以通過(guò)循環(huán)調(diào)用 recv 接口,可以在單個(gè)線程內(nèi)實(shí)現(xiàn)對(duì)所有連接的數(shù)據(jù)接收。但是上述模型絕不被推薦,因?yàn)檠h(huán)調(diào)用 recv將大幅度占用 CPU 使用率。

此外,在這個(gè)方案 recv 更多的是起到檢測(cè)“操作是否完成”的作用,實(shí)際操作系統(tǒng)提供了更為高效的檢測(cè)“操作是否完成”作用的接口,例如 select多路復(fù)用模式,可以次檢測(cè)多個(gè)連接是存活躍。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • IO
    IO
    +關(guān)注

    關(guān)注

    0

    文章

    448

    瀏覽量

    39160
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    3

    文章

    1372

    瀏覽量

    40293
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11304

    瀏覽量

    209536
  • 網(wǎng)絡(luò)
    +關(guān)注

    關(guān)注

    14

    文章

    7568

    瀏覽量

    88796
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Verilog語(yǔ)言中阻塞阻塞賦值的不同

    來(lái)源:《Verilog數(shù)字系統(tǒng)設(shè)計(jì)(夏宇聞)》 阻塞阻塞賦值的語(yǔ)言結(jié)構(gòu)是Verilog 語(yǔ)言中最難理解概念之一。甚至有些很有經(jīng)驗(yàn)的Verilog 設(shè)計(jì)工程師也不能完全正確地理解:何時(shí)使用
    的頭像 發(fā)表于 08-17 16:18 ?6384次閱讀

    Verilog阻塞阻塞原理分析

    Verilog阻塞阻塞原理分析在Verilog語(yǔ)言最難弄明白的結(jié)構(gòu)中“阻塞賦值”要算一個(gè)。甚至是一些很有經(jīng)驗(yàn)的工程師也不完全明白“
    發(fā)表于 11-23 12:02

    Java阻塞通信研究

    本文針對(duì)Java NIO 的特性做出分析與闡述,對(duì)網(wǎng)絡(luò)應(yīng)用中阻塞通信與阻塞通信、NIO的阻塞
    發(fā)表于 08-10 10:15 ?18次下載

    verilog中阻塞賦值和阻塞賦值

    阻塞阻塞語(yǔ)句作為verilog HDL語(yǔ)言的最大難點(diǎn)之一,一直困擾著FPGA設(shè)計(jì)者,即使是一個(gè)頗富經(jīng)驗(yàn)的設(shè)計(jì)工程師,也很容易在這個(gè)點(diǎn)上犯下一些不必要的錯(cuò)誤。阻塞
    發(fā)表于 03-15 10:57 ?7001次閱讀

    深入理解阻塞阻塞賦值

    這是一個(gè)很好的學(xué)習(xí)阻塞阻塞的資料,對(duì)于FPGA的學(xué)習(xí)有很大幫助。
    發(fā)表于 04-22 11:00 ?11次下載

    《Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》第8章、Linux設(shè)備驅(qū)動(dòng)中的阻塞阻塞IO

    《Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》第8章、Linux設(shè)備驅(qū)動(dòng)中的阻塞阻塞IO
    發(fā)表于 10-27 11:35 ?9次下載
    《Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》第8章、Linux設(shè)備驅(qū)動(dòng)中的<b class='flag-5'>阻塞</b>與<b class='flag-5'>非</b><b class='flag-5'>阻塞</b><b class='flag-5'>IO</b>

    深入分析同步阻塞網(wǎng)絡(luò)IO的內(nèi)部實(shí)現(xiàn)詳解

    網(wǎng)絡(luò)開(kāi)發(fā)模型中,有一種非常易于開(kāi)發(fā)同學(xué)使用的方式,那就是同步阻塞網(wǎng)絡(luò) IO(在 Java 中習(xí)慣叫 BIO)。
    的頭像 發(fā)表于 04-03 14:10 ?2030次閱讀
    深入分析同步<b class='flag-5'>阻塞</b><b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>IO</b>的內(nèi)部實(shí)現(xiàn)詳解

    簡(jiǎn)述阻塞賦值和阻塞賦值的可綜合性

    阻塞賦值和阻塞賦值的可綜合性 Blocking Assignment阻塞賦值和NonBlocking Assignment
    的頭像 發(fā)表于 05-12 09:45 ?2727次閱讀
    簡(jiǎn)述<b class='flag-5'>阻塞</b>賦值和<b class='flag-5'>非</b><b class='flag-5'>阻塞</b>賦值的可綜合性

    簡(jiǎn)述Verilog HDL中阻塞語(yǔ)句和阻塞語(yǔ)句的區(qū)別

    ? 在Verilog中有兩種類(lèi)型的賦值語(yǔ)句:阻塞賦值語(yǔ)句(“=”)和阻塞賦值語(yǔ)句(“=”)。正確地使用這兩種賦值語(yǔ)句對(duì)于Verilog的設(shè)計(jì)和仿真非常重要。 Verilog語(yǔ)言中講的阻塞
    的頭像 發(fā)表于 12-02 18:24 ?6223次閱讀
    簡(jiǎn)述Verilog HDL中<b class='flag-5'>阻塞</b>語(yǔ)句和<b class='flag-5'>非</b><b class='flag-5'>阻塞</b>語(yǔ)句的區(qū)別

    時(shí)序邏輯中的阻塞阻塞

    Verilog HDL的賦值語(yǔ)句分為阻塞賦值和阻塞賦值兩種。阻塞賦值是指在當(dāng)前賦值完成前阻塞其他類(lèi)型的賦值任務(wù),
    的頭像 發(fā)表于 03-15 13:53 ?3061次閱讀

    阻塞阻塞通信的區(qū)別 阻塞阻塞應(yīng)用場(chǎng)景

    阻塞通信(Blocking Communication):當(dāng)進(jìn)行阻塞通信時(shí),調(diào)用者在發(fā)起一個(gè)I/O操作后會(huì)被阻塞,直到該操作完成返回才能繼續(xù)執(zhí)行后續(xù)代碼。
    的頭像 發(fā)表于 06-15 17:32 ?6092次閱讀

    阻塞賦值與阻塞賦值

    ”=“阻塞賦值與”
    的頭像 發(fā)表于 09-12 09:06 ?1045次閱讀
    <b class='flag-5'>阻塞</b>賦值與<b class='flag-5'>非</b><b class='flag-5'>阻塞</b>賦值

    什么是阻塞阻塞?

    什么是阻塞阻塞?我們就用管道的讀寫(xiě)來(lái)舉例子。
    的頭像 發(fā)表于 03-25 10:04 ?506次閱讀

    socket阻塞阻塞的區(qū)別是什么

    在計(jì)算機(jī)編程中,socket 是一種通信端點(diǎn),用于在網(wǎng)絡(luò)中進(jìn)行數(shù)據(jù)傳輸。Socket 可以是阻塞的或阻塞的,這兩種模式在處理數(shù)據(jù)傳輸時(shí)有不同的行為。
    的頭像 發(fā)表于 08-16 11:13 ?681次閱讀

    socket編程中的阻塞阻塞

    網(wǎng)絡(luò)編程中, socket 是一個(gè)非常重要的概念,它提供了一個(gè)抽象層,使得開(kāi)發(fā)者可以不必關(guān)心底層的網(wǎng)絡(luò)通信細(xì)節(jié)。 socket 編程中的阻塞
    的頭像 發(fā)表于 11-01 16:13 ?212次閱讀