<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          太好玩了!一篇漫畫看懂網(wǎng)絡(luò)IO模型

          共 1874字,需瀏覽 4分鐘

           ·

          2021-06-18 04:44

          01

          大家好,我是一個進程,我的名字的小 P。
          我和很多其它小伙伴一樣,都由老大操作系統(tǒng)創(chuàng)建和管理。

          要問我是怎么來的,噓小點聲,不能讓那幫應(yīng)用開發(fā)們聽見。

          其實就是內(nèi)核的開發(fā)都認(rèn)為應(yīng)用開發(fā)是傻逼,怕應(yīng)用開發(fā)的代碼把服務(wù)器給搞壞。就設(shè)計了我們進程出來,專門運行各種用戶態(tài)的代碼。

          我們天然和內(nèi)核里的小伙伴們被隔離開來。我們大部分時間都運行在用戶態(tài),其它的兄弟們都一直運行在內(nèi)核態(tài)。

          我們沒有權(quán)限訪問硬盤、網(wǎng)卡等設(shè)備。

          如果我們需要這些功能的時候,需要通過系統(tǒng)調(diào)用先陷入到內(nèi)核態(tài)中。不過在陷入之前,系統(tǒng)調(diào)用入口要對我們執(zhí)行嚴(yán)格的安檢。

          好了背景就是這樣,今天我給大家講講我和我的好朋友們之間是怎么配合處理網(wǎng)絡(luò)IO的。

          02

          我們進程通過一個叫 socket 的哥們來和我們的用戶通信。但是實際上所有的 socket 以及整臺機器上的網(wǎng)絡(luò)包都是在內(nèi)核態(tài)來把控著的,我們只能拿到 socket 的編號。

          在很久很久以前,我們一般只處理一條 TCP 連接。

          我們通過一個叫 recvfrom 的系統(tǒng)調(diào)用來讀取我們的用戶發(fā)送過來的數(shù)據(jù)。假如運氣好的話,我們 recvfrom 的時候就可以把數(shù)據(jù)取走!

          但是其實根本我們不知道用戶那邊啥時候給我們打數(shù)據(jù)包過來,所以大部分情況下都不會運氣那么好。

          如果 read 的時候數(shù)據(jù)包沒有就緒,我們就得按照規(guī)矩主動把 CPU 讓出來。

          不過那時我們也確實只處理一條連接,連接上沒請求被阻塞掉也正常。

          后來老板不斷的壓榨我們,讓我們一個進程處理成百上千條連接。這時候 read 某條連接的時候,沒有數(shù)據(jù)就把我們掛起來,我們哪兒受得了哇,    我們還有其它好多連接要處理呢。

          而且頻繁的阻塞導(dǎo)致我的工作效率特別低下。 第一我們阻塞要花不少的時間保存我們當(dāng)前的工作狀態(tài),第二我們在 L1/L2/L3 等 cache 里準(zhǔn)備了好多工作時要用的緩存這下全沒用了。

          后來我們就給操作系統(tǒng)老大求了個情,要求把連接設(shè)置成非阻塞。

          我:“哥,我只是來看看這條連接上有沒有數(shù)據(jù)哈,有就給我,沒有也別阻塞我可以不?”
          操作系統(tǒng):“準(zhǔn)!”

          這下就好了,我就可以用循環(huán)遍歷的方式把我所有的 socket 挨個到內(nèi)核中去看一遍。

          但是我的問題是我還是不知道用戶啥時候把數(shù)據(jù)發(fā)過來。如果沒有就緒的,那我只能就頻繁循環(huán)地不斷地來內(nèi)核詢問。

          “去看看 1 號 socket 上有數(shù)據(jù)了沒?” “沒有”
          “去看看 2 號 socket 上有數(shù)據(jù)了沒?” “沒有”
          “去看看 3 號 socket 上有數(shù)據(jù)了沒?” “沒有”
          ...
          “去看看 1 號 socket 上有數(shù)據(jù)了沒?” “沒有”
          “去看看 2 號 socket 上有數(shù)據(jù)了沒?” “沒有”
          “去看看 3 號 socket 上有數(shù)據(jù)了沒?” “終于有啦”

          干這事可特么把我累壞個屁的了,運氣不好的時候我得訪問成千上萬次才能等到數(shù)據(jù)真正到來!

          03

          終于!!!

          后來操作系統(tǒng)老大在內(nèi)核態(tài)搞出了各種支持多路復(fù)用的新系統(tǒng)調(diào)用,它們是 select、poll、和 epoll。

          不過嘿嘿,我最喜歡 epoll 這個新家伙。

          我把需要觀察的 socket 都交給他,他替我都維護了起來了,據(jù)說是內(nèi)部用了一個叫啥紅黑樹的高深技術(shù)。

          不過其實愛用啥用啥,我只關(guān)注能解放我的體力就行。
          我是終于不用再不斷的輪詢了,每次我想要知道哪個 socket 上有請求的時候,直接進入內(nèi)核態(tài)查看一下就緒隊列就行了。

          這種爽歪歪的感覺,你們真的無法體會。這就是我喜歡用這個家伙的原因。

          如果請求很多,那我就可以一直 epoll_wait 獲取請求,一直處理,而不用阻塞。
          直到時間片耗盡被再次丟到就緒隊列等待調(diào)度。
          我的工作效率發(fā)揮到了極致,能處理的并發(fā)也越來越多。
          在 redis 上,我最高能達到每秒 10W 的qps,怎么樣厲害吧!

          不過在所有的連接上都沒有數(shù)據(jù)的時候,我也需要阻塞起來。
          這個我是接受的,畢竟沒活兒干的時候還占著 CPU 資源,我也會覺得怪不好意思。

          等網(wǎng)卡收到我的數(shù)據(jù)請求包的時候,我的另外一個兄弟軟中斷會從 epoll 的 wq 上找到我,把我叫醒。

          不過我所謂的叫醒,其實只是推入到就緒隊列而已。真正的調(diào)度還得等進程調(diào)度器老哥把我拉起來。

          看,我和 epoll、軟中斷、進程調(diào)度器等幾兄弟配合的是不是天衣無縫!

          瀏覽 53
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  草草影院网站 | 亚洲人成色77777在线播放 | 午夜性爱福利视频 | 岛国av不卡 | 亚洲高清无码视频在线观看 |