自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

圖解四種 IO 模型的前世今生

網(wǎng)絡(luò) 通信技術(shù)
在網(wǎng)絡(luò) IO 中,數(shù)據(jù)準(zhǔn)備可能是客戶端還有部分?jǐn)?shù)據(jù)還沒有發(fā)送、或者正在發(fā)送的途中,當(dāng)前內(nèi)核 Buffer 中的數(shù)據(jù)并不完整;而數(shù)據(jù)復(fù)制則是將內(nèi)核態(tài) Buffer 中的數(shù)據(jù)復(fù)制到用戶態(tài)的 Buffer 中去。

最近越來越認(rèn)為,在講解技術(shù)相關(guān)問題時(shí),大白話固然很重要,通俗易懂,讓人有想讀下去的欲望。但幾乎所有的事,都有兩面性,在看到其帶來好處時(shí),不妨想想是否也引入了不好的地方。

例如在博客中,過于大白話的語言的確會(huì)讓你閱讀起來更加順暢,也更容易理解。但這都是其他人理解,已經(jīng)咀嚼過了的,人家是已經(jīng)完全理解了,你從這些信息中大概可能會(huì)觀察不到全貌。所以,適當(dāng)?shù)陌自捠呛芎玫?,但這個(gè)度得控制一下。

接下來切入正文。

相信大家經(jīng)??吹竭@個(gè)問題:

BIO、NIO 和 AIO 有什么區(qū)別?

看到這個(gè)問題,可能你腦海中就會(huì)浮現(xiàn)以下這些字眼。比如 BIO 就是如果從內(nèi)核獲取數(shù)據(jù)會(huì)一直阻塞,直到數(shù)據(jù)準(zhǔn)備完畢返回。再比如 NIO,內(nèi)核在數(shù)據(jù)沒有準(zhǔn)備好時(shí)不會(huì)阻塞住,調(diào)用程序會(huì)一直詢問內(nèi)核數(shù)據(jù)是否 Ready。

雖然是正確的,字?jǐn)?shù)也很少。但是這樣一來,你看這些概念就不是理解,而是背誦了。其實(shí) BIO 和 NIO 這類的名詞還有一個(gè)共同的名字叫——IO模型,總共有:

IO 模型

由于信號(hào)驅(qū)動(dòng) IO 在實(shí)際中不常用,我們主要講以下四種模型:

  1. 同步阻塞
  2. 同步非阻塞
  3. IO 多路復(fù)用
  4. 異步 IO

這里還是通過例子來理解這 4 種 IO 模型:

假設(shè)此時(shí)客戶端正在發(fā)送一些數(shù)據(jù)到服務(wù)器,并且數(shù)據(jù)已經(jīng)通過客戶端的協(xié)議棧、網(wǎng)卡,陸陸續(xù)續(xù)的到達(dá)了服務(wù)器這邊的內(nèi)核態(tài) Buffer 中了。

不清楚用戶態(tài)和內(nèi)核態(tài)區(qū)別的可以看看《簡單聊聊用戶態(tài)和內(nèi)核態(tài)的區(qū)別》

對數(shù)據(jù)在網(wǎng)絡(luò)中是如何傳輸?shù)募?xì)節(jié)感興趣的,可以去看看我之前寫的文章 《請求數(shù)據(jù)包從發(fā)送到接收,都經(jīng)歷了什么?》。

同步阻塞 BIO

我們需要知道,內(nèi)核在處理數(shù)據(jù)的時(shí)候其實(shí)是分成了兩個(gè)階段:

  • 數(shù)據(jù)準(zhǔn)備
  • 數(shù)據(jù)復(fù)制

在網(wǎng)絡(luò) IO 中,數(shù)據(jù)準(zhǔn)備可能是客戶端還有部分?jǐn)?shù)據(jù)還沒有發(fā)送、或者正在發(fā)送的途中,當(dāng)前內(nèi)核 Buffer 中的數(shù)據(jù)并不完整;而數(shù)據(jù)復(fù)制則是將內(nèi)核態(tài) Buffer 中的數(shù)據(jù)復(fù)制到用戶態(tài)的 Buffer 中去。

當(dāng)調(diào)用線程發(fā)起 read 系統(tǒng)調(diào)用時(shí),如果此時(shí)內(nèi)核數(shù)據(jù)還沒有 Ready,調(diào)用線程會(huì)阻塞住,等待內(nèi)核 Buffer 的數(shù)據(jù)。內(nèi)核數(shù)據(jù)準(zhǔn)備就緒之后,會(huì)將內(nèi)核態(tài) Buffer 的數(shù)據(jù)復(fù)制到用戶態(tài) Buffer 中,這個(gè)過程中調(diào)用線程仍然是阻塞的,直到數(shù)據(jù)復(fù)制完成,整個(gè)流程用圖來表示就張這樣:

同步非阻塞 NIO

相信大家知道 Java 中有個(gè)包叫 nio,但那跟我們現(xiàn)在正在討論的 NIO 不是同一個(gè)概念。

現(xiàn)在正在討論的是 Non-Blocking IO,代表同步非阻塞,是一種基礎(chǔ)的 IO 模型。而 nio 包則是 New IO,里面的 IO 模型實(shí)際上是 IO多路復(fù)用,大家不要搞混淆了。

有了 BIO 的基礎(chǔ),這次我們直接來看圖:

NIO

還是分為兩個(gè)階段來討論。

數(shù)據(jù)準(zhǔn)備階段。此時(shí)用戶線程發(fā)起 read 系統(tǒng)調(diào)用,此時(shí)內(nèi)核會(huì)立即返回一個(gè)錯(cuò)誤,告訴用戶態(tài)數(shù)據(jù)還沒有 Read,然后用戶線程不停地發(fā)起請求,詢問內(nèi)核當(dāng)前數(shù)據(jù)的狀態(tài)。

數(shù)據(jù)復(fù)制階段。此時(shí)用戶線程還在不斷的發(fā)起請求,但是當(dāng)數(shù)據(jù) Ready 之后,用戶線程就會(huì)陷入阻塞,直到數(shù)據(jù)從內(nèi)核態(tài)復(fù)制到用戶態(tài)。

稍微總結(jié)一下,如果內(nèi)核態(tài)的數(shù)據(jù)沒有 Ready,用戶線程不會(huì)阻塞;但是如果內(nèi)核態(tài)數(shù)據(jù) Ready 了,即使當(dāng)前的 IO 模型是同步非阻塞,用戶線程仍然會(huì)進(jìn)入阻塞狀態(tài),直到數(shù)據(jù)復(fù)制完成,并不是絕對的非阻塞。

那 NIO 的好處是啥呢?顯而易見,實(shí)時(shí)性好,內(nèi)核態(tài)數(shù)據(jù)沒有 Ready 會(huì)立即返回。但是事情的兩面性就來了,頻繁的輪詢內(nèi)核,會(huì)占用大量的 CPU 資源,降低效率。

IO 多路復(fù)用

IO 多路復(fù)用實(shí)際上就解決了 NIO 中的頻繁輪詢 CPU 的問題。在之前的 BIO 和 NIO 中只涉及到一種系統(tǒng)調(diào)用——read,在 IO 多路復(fù)用中要引入新的系統(tǒng)調(diào)用——select。

read 用于讀取內(nèi)核態(tài) Buffer 中的數(shù)據(jù),而 select 你可以理解成 MySQL 中的同名關(guān)鍵字,用于查詢 IO 的就緒狀態(tài)。

在 NIO 中,內(nèi)核態(tài)數(shù)據(jù)沒有 Ready 會(huì)導(dǎo)致用戶線程不停的輪詢,從而拉滿 CPU。而在 IO 多路復(fù)用中調(diào)用了 select 之后,只要數(shù)據(jù)沒有準(zhǔn)備好,用戶線程就會(huì)阻塞住,避免了頻繁的輪詢當(dāng)前的 IO 狀態(tài),用圖來表示的話是這樣:

IO 多路復(fù)用

異步 AIO

該模型的實(shí)現(xiàn)就如其名,是異步的。用戶線程發(fā)起 read 系統(tǒng)調(diào)用之后,無論內(nèi)核 Buffer 數(shù)據(jù)是否 Ready,都不會(huì)阻塞,而是立即返回。

內(nèi)核在收到請求之后,會(huì)開始準(zhǔn)備數(shù)據(jù),準(zhǔn)備好了&復(fù)制完成之后會(huì)由內(nèi)核發(fā)送一個(gè) Signal 給用戶線程,或者回調(diào)用戶線程注冊的接口進(jìn)行通知。用戶線程收到通知之后就可以去讀取用戶態(tài) Buffer 的數(shù)據(jù)了。

 

AIO

由于這種實(shí)現(xiàn)方式,異步 IO 有時(shí)也被叫做信號(hào)驅(qū)動(dòng) IO。相信你也發(fā)現(xiàn)了,這種方式最重要的是需要 OS 的支持,如果 OS 不支持就直接完蛋。

Linux 系統(tǒng)在 2.6 版本的時(shí)候才引入了異步IO,不過那個(gè)時(shí)候并不算真正的異步 IO,因?yàn)閮?nèi)核并不支持,底層其實(shí)是通過 IO 多路復(fù)用實(shí)現(xiàn)的。而到了 Linux 5.1 時(shí),才通過 io_uring 實(shí)現(xiàn)了真 AIO。

【編輯推薦】

 

責(zé)任編輯:姜華 來源: SH的全棧筆記
相關(guān)推薦

2016-08-04 15:10:12

服務(wù)器虛擬化網(wǎng)絡(luò)

2011-08-23 09:52:31

CSS

2015-11-18 14:14:11

OPNFVNFV

2025-02-12 11:25:39

2014-07-30 10:55:27

2022-03-15 11:01:39

KubernetesLinux平滑升級

2010-06-09 10:04:59

UML類圖

2011-11-21 10:20:36

2014-07-21 12:57:25

諾基亞微軟裁員

2013-05-23 16:23:42

Windows Azu微軟公有云

2014-07-15 10:31:07

asyncawait

2016-12-29 13:34:04

阿爾法狗圍棋計(jì)算機(jī)

2016-12-29 18:21:01

2019-06-04 09:00:07

Jenkins X開源開發(fā)人員

2021-06-17 07:08:19

Tapablewebpack JavaScript

2012-05-18 16:54:21

FedoraFedora 17

2016-11-08 19:19:06

2016-11-03 13:33:31

2013-11-14 16:03:23

Android設(shè)計(jì)Android Des

2011-05-13 09:43:27

產(chǎn)品經(jīng)理PM
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)