最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

如何從Linux內(nèi)核看socket底層的本質(zhì)(IO)(這兩點(diǎn)入手~)

2022-05-24 20:28 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

一、I/O 模型

一個(gè)輸入操作通常包括兩個(gè)階段:

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

  2. 從內(nèi)核向進(jìn)程復(fù)制數(shù)據(jù)

  • 對(duì)于一個(gè)套接字上的輸入操作,第一步通常涉及等待數(shù)據(jù)從網(wǎng)絡(luò)中到達(dá)。當(dāng)所等待數(shù)據(jù)到達(dá)時(shí),它被復(fù)制到內(nèi)核中的某個(gè)緩沖區(qū)。第二步就是把數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到應(yīng)用進(jìn)程緩沖區(qū)。

Unix 有五種 I/O 模型:

  1. 阻塞式 I/O

  2. 非阻塞式 I/O

  3. I/O 復(fù)用(select 和 poll)

  4. 信號(hào)驅(qū)動(dòng)式 I/O(SIGIO)

  5. 異步 I/O(AIO)

阻塞式 I/O

  • 應(yīng)用進(jìn)程被阻塞,直到數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到應(yīng)用進(jìn)程緩沖區(qū)中才返回。

  • 應(yīng)該注意到,在阻塞的過(guò)程中,其它應(yīng)用進(jìn)程還可以執(zhí)行,因此阻塞不意味著整個(gè)操作系統(tǒng)都被阻塞。因?yàn)槠渌鼞?yīng)用進(jìn)程還可以執(zhí)行,所以不消耗 CPU 時(shí)間,這種模型的 CPU 利用率會(huì)比較高。

  • 下圖中,recvfrom() 用于接收 Socket 傳來(lái)的數(shù)據(jù),并復(fù)制到應(yīng)用進(jìn)程的緩沖區(qū) buf 中。這里把 recvfrom() 當(dāng)成系統(tǒng)調(diào)用。



非阻塞式 I/O

  • 應(yīng)用進(jìn)程執(zhí)行系統(tǒng)調(diào)用之后,內(nèi)核返回一個(gè)錯(cuò)誤碼。應(yīng)用進(jìn)程可以繼續(xù)執(zhí)行,但是需要不斷的執(zhí)行系統(tǒng)調(diào)用來(lái)獲知 I/O 是否完成,這種方式稱(chēng)為輪詢(polling)。

  • 由于 CPU 要處理更多的系統(tǒng)調(diào)用,因此這種模型的 CPU 利用率比較低。


I/O 復(fù)用

  • 使用 select 或者 poll 等待數(shù)據(jù),并且可以等待多個(gè)套接字中的任何一個(gè)變?yōu)榭勺x。這一過(guò)程會(huì)被阻塞,當(dāng)某一個(gè)套接字可讀時(shí)返回,之后再使用 recvfrom 把數(shù)據(jù)從內(nèi)核復(fù)制到進(jìn)程中。

  • 它可以讓單個(gè)進(jìn)程具有處理多個(gè) I/O 事件的能力。又被稱(chēng)為 Event Driven I/O,即事件驅(qū)動(dòng) I/O。

  • 如果一個(gè) Web 服務(wù)器沒(méi)有 I/O 復(fù)用,那么每一個(gè) Socket 連接都需要?jiǎng)?chuàng)建一個(gè)線程去處理。如果同時(shí)有幾萬(wàn)個(gè)連接,那么就需要?jiǎng)?chuàng)建相同數(shù)量的線程。相比于多進(jìn)程和多線程技術(shù),I/O 復(fù)用不需要進(jìn)程線程創(chuàng)建和切換的開(kāi)銷(xiāo),系統(tǒng)開(kāi)銷(xiāo)更小。

【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺(jué)得比較好的學(xué)習(xí)書(shū)籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。?!前100名進(jìn)群領(lǐng)取,額外贈(zèng)送一份價(jià)值699的內(nèi)核資料包(含視頻教程、電子書(shū)、實(shí)戰(zhàn)項(xiàng)目及代碼)? ? ?



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

  • 應(yīng)用進(jìn)程使用 sigaction 系統(tǒng)調(diào)用,內(nèi)核立即返回,應(yīng)用進(jìn)程可以繼續(xù)執(zhí)行,也就是說(shuō)等待數(shù)據(jù)階段應(yīng)用進(jìn)程是非阻塞的。內(nèi)核在數(shù)據(jù)到達(dá)時(shí)向應(yīng)用進(jìn)程發(fā)送 SIGIO 信號(hào),應(yīng)用進(jìn)程收到之后在信號(hào)處理程序中調(diào)用 recvfrom 將數(shù)據(jù)從內(nèi)核復(fù)制到應(yīng)用進(jìn)程中。

  • 相比于非阻塞式 I/O 的輪詢方式,信號(hào)驅(qū)動(dòng) I/O 的 CPU 利用率更高。

異步 I/O

  • 應(yīng)用進(jìn)程執(zhí)行 aio_read 系統(tǒng)調(diào)用會(huì)立即返回,應(yīng)用進(jìn)程可以繼續(xù)執(zhí)行,不會(huì)被阻塞,內(nèi)核會(huì)在所有操作完成之后向應(yīng)用進(jìn)程發(fā)送信號(hào)。

  • 異步 I/O 與信號(hào)驅(qū)動(dòng) I/O 的區(qū)別在于,異步 I/O 的信號(hào)是通知應(yīng)用進(jìn)程 I/O 完成,而信號(hào)驅(qū)動(dòng) I/O 的信號(hào)是通知應(yīng)用進(jìn)程可以開(kāi)始 I/O。

五大 I/O 模型比較

  1. 同步 I/O:將數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到應(yīng)用進(jìn)程緩沖區(qū)的階段(第二階段),應(yīng)用進(jìn)程會(huì)阻塞。

  2. 異步 I/O:第二階段應(yīng)用進(jìn)程不會(huì)阻塞。

  • 同步 I/O 包括阻塞式 I/O、非阻塞式 I/O、I/O 復(fù)用和信號(hào)驅(qū)動(dòng) I/O ,它們的主要區(qū)別在第一個(gè)階段。

  • 非阻塞式 I/O 、信號(hào)驅(qū)動(dòng) I/O 和異步 I/O 在第一階段不會(huì)阻塞。

二、I/O 復(fù)用

  • select/poll/epoll 都是 I/O 多路復(fù)用的具體實(shí)現(xiàn),select 出現(xiàn)的最早,之后是 poll,再是 epoll。

select

  • select 允許應(yīng)用程序監(jiān)視一組文件描述符,等待一個(gè)或者多個(gè)描述符成為就緒狀態(tài),從而完成 I/O 操作。

  1. fd_set 使用數(shù)組實(shí)現(xiàn),數(shù)組大小使用 FD_SETSIZE 定義,所以只能監(jiān)聽(tīng)少于 FD_SETSIZE 數(shù)量的描述符。有三種類(lèi)型的描述符類(lèi)型:readset、writeset、exceptset,分別對(duì)應(yīng)讀、寫(xiě)、異常條件的描述符集合。

  2. timeout 為超時(shí)參數(shù),調(diào)用 select 會(huì)一直阻塞直到有描述符的事件到達(dá)或者等待的時(shí)間超過(guò) timeout。

  3. 成功調(diào)用返回結(jié)果大于 0,出錯(cuò)返回結(jié)果為 -1,超時(shí)返回結(jié)果為 0。

poll

  • poll 的功能與 select 類(lèi)似,也是等待一組描述符中的一個(gè)成為就緒狀態(tài)。

  • poll 中的描述符是 pollfd 類(lèi)型的數(shù)組,pollfd 的定義如下:

比較

1. 功能

  • select 和 poll 的功能基本相同,不過(guò)在一些實(shí)現(xiàn)細(xì)節(jié)上有所不同。

  1. select 會(huì)修改描述符,而 poll 不會(huì);

  2. select 的描述符類(lèi)型使用數(shù)組實(shí)現(xiàn),F(xiàn)D_SETSIZE 大小默認(rèn)為 1024,因此默認(rèn)只能監(jiān)聽(tīng)少于 1024 個(gè)描述符。如果要監(jiān)聽(tīng)更多描述符的話,需要修改 FD_SETSIZE 之后重新編譯;而 poll 沒(méi)有描述符數(shù)量的限制;

  3. poll 提供了更多的事件類(lèi)型,并且對(duì)描述符的重復(fù)利用上比 select 高。

  4. 如果一個(gè)線程對(duì)某個(gè)描述符調(diào)用了 select 或者 poll,另一個(gè)線程關(guān)閉了該描述符,會(huì)導(dǎo)致調(diào)用結(jié)果不確定。

2. 速度

  • select 和 poll 速度都比較慢,每次調(diào)用都需要將全部描述符從應(yīng)用進(jìn)程緩沖區(qū)復(fù)制到內(nèi)核緩沖區(qū)。

3. 可移植性

  • 幾乎所有的系統(tǒng)都支持 select,但是只有比較新的系統(tǒng)支持 poll。

epoll

  • epoll_ctl() 用于向內(nèi)核注冊(cè)新的描述符或者是改變某個(gè)文件描述符的狀態(tài)。已注冊(cè)的描述符在內(nèi)核中會(huì)被維護(hù)在一棵紅黑樹(shù)上,通過(guò)回調(diào)函數(shù)內(nèi)核會(huì)將 I/O 準(zhǔn)備好的描述符加入到一個(gè)鏈表中管理,進(jìn)程調(diào)用 epoll_wait() 便可以得到事件完成的描述符。

  • 從上面的描述可以看出,epoll 只需要將描述符從進(jìn)程緩沖區(qū)向內(nèi)核緩沖區(qū)拷貝一次,并且進(jìn)程不需要通過(guò)輪詢來(lái)獲得事件完成的描述符。

  • epoll 僅適用于 Linux OS。

  • epoll 比 select 和 poll 更加靈活而且沒(méi)有描述符數(shù)量限制。

  • epoll 對(duì)多線程編程更有友好,一個(gè)線程調(diào)用了 epoll_wait() 另一個(gè)線程關(guān)閉了同一個(gè)描述符也不會(huì)產(chǎn)生像 select 和 poll 的不確定情況。

工作模式

  • epoll 的描述符事件有兩種觸發(fā)模式:LT(level trigger)和 ET(edge trigger)。

1. LT 模式

  • 當(dāng) epoll_wait() 檢測(cè)到描述符事件到達(dá)時(shí),將此事件通知進(jìn)程,進(jìn)程可以不立即處理該事件,下次調(diào)用 epoll_wait() 會(huì)再次通知進(jìn)程。是默認(rèn)的一種模式,并且同時(shí)支持 Blocking 和 No-Blocking。

2. ET 模式

  • 和 LT 模式不同的是,通知之后進(jìn)程必須立即處理事件,下次再調(diào)用 epoll_wait() 時(shí)不會(huì)再得到事件到達(dá)的通知。

  • 很大程度上減少了 epoll 事件被重復(fù)觸發(fā)的次數(shù),因此效率要比 LT 模式高。只支持 No-Blocking,以避免由于一個(gè)文件句柄的阻塞讀/阻塞寫(xiě)操作把處理多個(gè)文件描述符的任務(wù)餓死。

應(yīng)用場(chǎng)景

  • 很容易產(chǎn)生一種錯(cuò)覺(jué)認(rèn)為只要用 epoll 就可以了,select 和 poll 都已經(jīng)過(guò)時(shí)了,其實(shí)它們都有各自的使用場(chǎng)景。

select 應(yīng)用場(chǎng)景

  • select 的 timeout 參數(shù)精度為微秒,而 poll 和 epoll 為毫秒,因此 select 更加適用于實(shí)時(shí)性要求比較高的場(chǎng)景,比如核反應(yīng)堆的控制。

  • select 可移植性更好,幾乎被所有主流平臺(tái)所支持。

poll 應(yīng)用場(chǎng)景

  • poll 沒(méi)有最大描述符數(shù)量的限制,如果平臺(tái)支持并且對(duì)實(shí)時(shí)性要求不高,應(yīng)該使用 poll 而不是 select。

epoll 應(yīng)用場(chǎng)景

  • 只需要運(yùn)行在 Linux 平臺(tái)上,有大量的描述符需要同時(shí)輪詢,并且這些連接最好是長(zhǎng)連接。

  • 需要同時(shí)監(jiān)控小于 1000 個(gè)描述符,就沒(méi)有必要使用 epoll,因?yàn)檫@個(gè)應(yīng)用場(chǎng)景下并不能體現(xiàn) epoll 的優(yōu)勢(shì)。

  • 需要監(jiān)控的描述符狀態(tài)變化多,而且都是非常短暫的,也沒(méi)有必要使用 epoll。因?yàn)?epoll 中的所有描述符都存儲(chǔ)在內(nèi)核中,造成每次需要對(duì)描述符的狀態(tài)改變都需要通過(guò) epoll_ctl() 進(jìn)行系統(tǒng)調(diào)用,頻繁系統(tǒng)調(diào)用降低效率。并且 epoll 的描述符存儲(chǔ)在內(nèi)核,不容易調(diào)試。


如何從Linux內(nèi)核看socket底層的本質(zhì)(IO)(這兩點(diǎn)入手~)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
柘城县| 张北县| 荆门市| 雅安市| 山东省| 武冈市| 清丰县| 奉节县| 获嘉县| 楚雄市| 通城县| 临猗县| 禄丰县| 屏南县| 法库县| 教育| 新野县| 乐山市| 东光县| 迁西县| 延长县| 盐源县| 平塘县| 扶沟县| 佳木斯市| 芦溪县| 西宁市| 同江市| 东山县| 华安县| 个旧市| 托里县| 丰原市| 中牟县| 黔江区| 高尔夫| 宜春市| 台东县| 宣恩县| 湟中县| 湄潭县|