當(dāng)前位置:首頁 > IT技術(shù) > 其他 > 正文

I/O模型剖析
2022-04-25 23:07:21

1.服務(wù)端處理網(wǎng)絡(luò)請求過程

I/O模型剖析_I/O模型剖析

IO分為:

網(wǎng)絡(luò)IO:本質(zhì)是socket文件讀取;上圖中紅線部分

磁盤IO:上圖中藍線部分

由上圖可知:IO都分為了兩個階段

1.將數(shù)據(jù)從文件先加載至內(nèi)核內(nèi)存空間(緩沖區(qū))--時間長
2.將數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到用戶空間的進程的內(nèi)存中--時間短

服務(wù)端處理網(wǎng)絡(luò)請求的過程

1.客戶端發(fā)起請求,數(shù)據(jù)發(fā)送到網(wǎng)卡
2.將網(wǎng)卡中數(shù)據(jù)通過DMA機制復(fù)制到內(nèi)核緩沖區(qū)
3.內(nèi)核緩沖區(qū)復(fù)制到用戶空間(比如要:GET index.html)
-------------------
4.web服務(wù)器收到請求數(shù)據(jù),因為應(yīng)用程序無法與硬件打交道,所以向內(nèi)核空間發(fā)起系統(tǒng)調(diào)用
5.內(nèi)核空間收到信息,cpu發(fā)出指令,讓DMA設(shè)備去磁盤獲取index.html,并拷貝到內(nèi)核緩沖區(qū)
6.內(nèi)核緩沖區(qū)再復(fù)制到用戶空間
-------------------
7.web服務(wù)器收到數(shù)據(jù),然后構(gòu)建響應(yīng)報文,再發(fā)送給內(nèi)核空間的socket buffer
8.socket buffer 在發(fā)送給網(wǎng)卡
9.通過網(wǎng)卡把響應(yīng)報文發(fā)送給客戶端

2.什么是DMA

DMA:直接內(nèi)存訪問

I/O模型剖析_I/O模型剖析_02

PIO 程序的輸入輸出模型,--所有操作都需要CPU參與
DMA 直接內(nèi)存訪問;只需要cpu發(fā)送指令,讓DMA設(shè)備去把磁盤數(shù)據(jù)拷貝到內(nèi)存,降低CPU的使用率

3.IO模型

同步,異步,阻塞,非阻塞的理解

I/O模型剖析_I/O模型剖析_03

比如上圖:A是領(lǐng)導(dǎo)  B是員工
現(xiàn)在A讓B去做一件事情

同步就是:領(lǐng)導(dǎo)自己去詢問事情是否做完
異步就是:員工主動告知領(lǐng)導(dǎo)事情的進度

阻塞就是:事情非常緊急需要馬上解決,領(lǐng)導(dǎo)必須盯著員工把事情做完,不能干其他的
非阻塞:領(lǐng)導(dǎo)在員工做事情時,可以去喝喝茶,打打高爾夫...等等

A對應(yīng):應(yīng)用程序
B對應(yīng):內(nèi)核
只有讓內(nèi)核多做事情,應(yīng)用程序少做,這樣才能實現(xiàn)高并發(fā)

衍生出

同步阻塞,同步非阻塞,異步阻塞,異步非阻塞

場景:用燒水壺?zé)?br/>
同步阻塞就是:買的燒水壺是無聲的,為了把水燒開,并且不能讓水噴出來,就只能守著燒

同步非阻塞:買的燒水壺也是無聲的,只需要把水燒開就行,不管開水會不會噴出,所以我就可以在燒水時,去看看電視
偶爾去看看水是否燒開就行

異步阻塞:這次買的燒水壺可以語音提示,燒開了會提醒,如果我此時還守著,不是有病嘛,所以這沒意義

異步非阻塞:水燒開自動提醒我,在燒水時我可以開心看電視

4.五中IO模型

阻塞型、非阻塞型、復(fù)用型、信號驅(qū)動型、異步

4.1.阻塞型

I/O模型剖析_I/O模型剖析_04

理解場景:釣魚

去釣魚,那人必須守著
數(shù)據(jù)準(zhǔn)備好:就好比魚兒上鉤,這個過程是很漫長的
復(fù)制完成:好比當(dāng)魚兒上鉤,把魚兒放到桶里,這個過程很快

在釣魚的過程中,為了不讓魚兒跑掉,你必須一直守著,不能干其他的;所以一直是阻塞的

4.2.非阻塞型

I/O模型剖析_I/O模型剖析_05

理解場景: 釣魚,釣魚旁邊有個麻將館

釣魚時,把魚竿搞好,就去麻將館打麻將了...
打一局,我就去看看魚兒上鉤沒有...
當(dāng)魚兒上鉤了,這個時候我必須在場把魚兒放在桶里

在魚兒上鉤過程中,我都跑去打麻將了,只是偶爾去看看魚兒是否上鉤,也只有把魚放在桶里這階段我在場,所以
只有這段時間是阻塞的

4.3.復(fù)用型

I/O模型剖析_I/O模型剖析_06

理解場景:我雇了一只貓去守著釣魚,而且這次拿了很多釣竿

讓貓在河邊守著,但是呢,我又怕貓偷吃,所以我也只能盯著貓不能去打麻將了,這階段我是阻塞的
當(dāng)有釣竿魚上鉤了,貓就叫我,然后我就過去把魚放在桶里,所以我從頭到尾一直都是阻塞的....

4.4.信號驅(qū)動型

I/O模型剖析_I/O模型剖析_07

理解場景:我買了一個帶語音提示的魚竿

這次,我把魚竿搞好,我也依然去旁邊的麻將館打麻將了,
當(dāng)魚兒上鉤了,就語音提示我,主人,主人,魚上鉤了,然后我就去把魚兒放在桶里

只有把魚放在桶里,我需要去河邊,這段時間我是阻塞的

4.5.異步

I/O模型剖析_I/O模型剖析_08

理解場景:由于前幾次都是空軍,這次我就聘請了一個釣魚達人去釣

釣魚達人在釣魚,我就去打麻將..
我麻將打完了,釣魚達人,就把魚兒給我了

5.五種I/O模型比較

I/O模型剖析_I/O模型剖析_09

阻塞型:一直都阻塞
非阻塞:只有魚兒放桶里是阻塞
復(fù)用型:也是一直阻塞
信號驅(qū)動:只有魚兒放桶里是阻塞
異步:完全不阻塞

6.模型實現(xiàn)的方式

Select:   #Linux實現(xiàn)         對應(yīng)I/O復(fù)用模型      BSD4.2最早實現(xiàn),POSIX標(biāo)準(zhǔn),一般操作系統(tǒng)均有實現(xiàn)
Poll: #Linux實現(xiàn), 對應(yīng)I/O復(fù)用模型 System V unix最早實現(xiàn)
Epoll: #Linux特有, 對應(yīng)I/O復(fù)用模型 具有信號驅(qū)動I/O模型的某些特性

Kqueue: #FreeBSD實現(xiàn), 對應(yīng)I/O復(fù)用模型 具有信號驅(qū)動I/O模型某些特性
/dev/poll:#SUN的Solaris實現(xiàn) 對應(yīng)I/O復(fù)用模型 具有信號驅(qū)動I/O模型的某些特性
Iocp #Windows實現(xiàn), 對應(yīng)第5種(異步I/O)模型

7.select/poll/epoll

I/O模型剖析_I/O模型剖析_10

I/O模型剖析_I/O模型剖析_11

7.1.select

Select:POSIX所規(guī)定,目前幾乎在所有的平臺上支持,其良好跨平臺支持也是它的一個優(yōu)點,本質(zhì)上是通過設(shè)置或
者檢查存放fd標(biāo)志位的數(shù)據(jù)結(jié)構(gòu)來進行下一步處理

#缺點
1)單個進程能夠監(jiān)視的文件描述符的數(shù)量存在最大限制,在Linux上一般為1024,可以通過修改宏定義FD_SETSIZE,
再重新編譯內(nèi)核實現(xiàn),但是這樣也會造成效率的降低
2)單個進程可監(jiān)視的fd數(shù)量被限制,默認是1024,修改此值需要重新編譯內(nèi)核
3)對socket是線性掃描,即采用輪詢的方法,效率較低
4)select 采取了內(nèi)存拷貝方法來實現(xiàn)內(nèi)核將 FD 消息通知給用戶空間,這樣一個用來存放大量fd的數(shù)據(jù)結(jié)構(gòu),
這樣會使得用戶空間和內(nèi)核空間在傳遞該結(jié)構(gòu)時復(fù)制開銷大

7.2.poll

1)本質(zhì)上和select沒有區(qū)別,它將用戶傳入的數(shù)組拷貝到內(nèi)核空間,然后查詢每個fd對應(yīng)的設(shè)備狀態(tài)
2)其沒有最大連接數(shù)的限制,原因是它是基于鏈表來存儲的
3)大量的fd的數(shù)組被整體復(fù)制于用戶態(tài)和內(nèi)核地址空間之間,而不管這樣的復(fù)制是不是有意義
4)poll特點是"水平觸發(fā)",如果報告了fd后,沒有被處理,那么下次poll時會再次報告該fd

7.3.epoll

epoll:在Linux 2.6內(nèi)核中提出的select和poll的增強版本
支持水平觸發(fā)LT和邊緣觸發(fā)ET,最大的特點在于邊緣觸發(fā),它只告訴進程哪些fd剛剛變?yōu)榫托钁B(tài),并且只會通知一次
使用"事件"的就緒通知方式,通過epoll_ctl注冊fd,一旦該fd就緒,內(nèi)核就會采用類似callback的回調(diào)機制來激
活該fd,epoll_wait便可以收到通知

#優(yōu)點:
1)沒有最大并發(fā)連接的限制:能打開的FD的上限遠大于1024(1G的內(nèi)存能監(jiān)聽約10萬個端口),具體查看
/proc/sys/fs/file-max,此值和系統(tǒng)內(nèi)存大小相關(guān)
2)效率提升:非輪詢的方式,不會隨著FD數(shù)目的增加而效率下降;只有活躍可用的FD才會調(diào)用callback函數(shù),
即epoll最大的優(yōu)點就在于它只管理"活躍"的連接,而跟連接總數(shù)無關(guān)
3)內(nèi)存拷貝,利用mmap(Memory Mapping)加速與內(nèi)核空間的消息傳遞;即epoll使用mmap減少復(fù)制開銷

邊緣觸發(fā):只通知一次

8.什么是零拷貝

傳統(tǒng)Linux中 I/O 的問題

傳統(tǒng)的Linux系統(tǒng)的標(biāo)準(zhǔn) I/O 接口(read、write)是基于數(shù)據(jù)拷貝的,也就是數(shù)據(jù)都是 copy_to_user 或者
copy_from_user,這樣做的好處是,通過中間緩存的機制,減少磁盤 I/O 的操作,
但是壞處也很明顯,大量數(shù)據(jù)的拷貝,用戶態(tài)和內(nèi)核態(tài)的頻繁切換,會消耗大量的 CPU 資源,嚴重影響數(shù)據(jù)傳輸?shù)?br/>性能
統(tǒng)計表明,在Linux協(xié)議棧中,數(shù)據(jù)包在內(nèi)核態(tài)和用戶態(tài)之間的拷貝所用的時間甚至占到了數(shù)據(jù)包整個處理流
程時間的57.1%
零拷貝就是上述問題的一個解決方案,盡量避免拷貝操作來緩解 CPU 的壓力。
零拷貝并沒有真正做到"0"拷貝,它更多是一種思想,很多的零拷貝技術(shù)都是基于這個思想去做的優(yōu)化

8.1.原始數(shù)據(jù)拷貝操作

I/O模型剖析_I/O模型剖析_12

8.2.MMAP:Memory Mapping

I/O模型剖析_I/O模型剖析_13

8.3.SENDFILE

I/O模型剖析_I/O模型剖析_14

8.4.DMA 輔助的 SENDFILE

I/O模型剖析_I/O模型剖析_15

9.Httpd MPM

HTTP中的三種請求處理模式(MPM)的區(qū)別

(1)prefork(預(yù)派生模式):多進程I/o模型,每個進程相應(yīng)一個請求  #-->>進程模型,兩級結(jié)構(gòu)
主進程--子進程--線程--請求
|--子進程--線程--請求
|--子進程--線程--請求
優(yōu)點:穩(wěn)定
缺點:慢,占用資源(內(nèi)存),不適用于高并發(fā)場景
使用select 模型,最大并發(fā)1024


(2)worker:復(fù)用的多進程I/O模型,多進程多線程 #-->>線程模型,三級結(jié)構(gòu)
主進程--子進程--線程--請求
| --線程--請求
| --線程--請求
|--子進程--線程--請求
| --線程--請求
| --線程--請求
優(yōu)點:相比prefork,占用內(nèi)存較少,可以同時處理更多的請求
缺點:使用keep-alive的長連接方式,某個線程會一直被占據(jù),即使沒有傳輸數(shù)據(jù),也需要一直等待到超時才會被釋放。


(3)event 事件驅(qū)動模型(epoll),增加了一個監(jiān)聽線程 #-->>線程模型,三級結(jié)構(gòu)
監(jiān)聽線程:用于向工作線程分配任務(wù)并和客戶端保持會話連接,超時之后監(jiān)聽線程會刪除socket,工作線程只處理用戶請求,處理完之后將會話保持交于監(jiān)聽線程,自己去處理新的請求,不再負責(zé)會話保持
主進程--子進程--監(jiān)聽線程--請求1 空請求不被分配 請求3
| |--工作線程--請求1
| |--工作線程--請求3
| |--工作線程 處理完成請求,將keep-alived交給監(jiān)聽線程,自己開始等待處理新請求
與worker進程很像,最大的區(qū)別在于,它解決了keep-alive場景下,長期被占用的線程的資源浪費問題
優(yōu)點:單線程響應(yīng)多請求,占據(jù)更少的內(nèi)存,高并發(fā)下表現(xiàn)更優(yōu)秀
缺點:沒有線程安全控制

本文摘自 :https://blog.51cto.com/t

開通會員,享受整站包年服務(wù)立即開通 >