CPU明明8個核,網卡為啥拼命折騰1號核?
前段時間分享的一篇《完了!CPU 一味求快出事了》得到了眾多網友的好評,今天我們就來繼續探討 CPU 的那些事!
CPU明明8個核,網卡為啥拼命折騰1號核?
中斷機制
我是 CPU 一號車間的阿 Q,我又來了!
我們日常的工作就是不斷執行代碼指令,不過這看似簡單的工作背后其實也并不輕松。
咱不能悶著頭啥也不管一個勁的只管執行代碼,還得和連接在主板上的其他單位打交道。
經常保持聯系的有鍵盤、鼠標、磁盤,哦對,還有網卡,這家伙最近把我惹到了,待會再說這事兒。
原以為內存那家伙已經夠慢的了,沒想到跟上面這幾位通個信比他更慢,咱 CPU 工廠的時間一刻值千金,不能干等著,耽誤工夫。后來廠里一合計,想了個叫中斷的辦法。
在我們車間裝了個大燈,這些單位想聯系我們辦事兒,就先給我們發一個中斷信號,大燈就會自動亮起。
我們平時工作執行代碼指令的時候,每執行一條指令就會瞅一眼看看大燈有沒有亮起來。
一旦發現燈亮了,就把手頭的工作先放一邊,去處理一下。
我們記性很差的,等會處理了完了還得回來接著原來的活繼續干,為了等會回來還能接的起來,走之前得把當前執行的這個線程的各個寄存器的值,執行到哪里了等等這些信息都保存在這個線程的棧里去。
不過有時候我們在執行非常重要的事情的時候,就不想被他們打斷。于是我們又在車間里那個 eflags 寄存器中設置了一個標記,如果是 1 我們才允許被打斷,如果是 0 那就算天王老子找我們也不管了。
哦不對,還有一種不可以屏蔽的中斷 NMI,走得是綠色通道。不過我可不期望有這種事情發生,因為一般都沒有好事,不是電源斷電就是溫度過高,或者總線出了錯誤等這之類嚴重的事情。
8259A PIC
還有一個問題,找我們辦事兒的單位有很多,我們得要區分開來,到底是誰來消息了,而且要是他們一起來找,按什么樣優先級順序處理,也是一件頭疼的事情。
為此,廠里單獨組建了一個全資的子公司來負責這事兒,他就是可編程中斷控制器 PIC,外號 8259A,其他單位想聯系我們都得通過這個 PIC,我們只需要和 PIC 進行對接就可以了。
我們給辦事單位都分配了一個編號,叫做中斷向量。我們還準備了一個表格叫中斷描述符表 IDT,表格里記錄了很多信息,其中就有處理這個中斷號對應的函數地址。
我們找 PIC 拿到編號后就執行處理函數就 OK 了。
這個表格有點大,足足有 256 項,咱 CPU 車間空間有限,放不下,就把它放在內存那家伙那里了,為了能快速找到這個表,專門添置了一個叫 idtr 的寄存器指向這個表格。
其實除了中斷,我們在執行指令的時候如果遇到了異常情況,也會去這個表里執行異常處理函數,最常見的比如遇到了除數是 0,內存地址錯誤等等情況。
這種情況下,我們必須主動放下手里的活,去處理異常,所以我們也說異常是同步的,而中斷不知道什么時候發生,所以是異步的。
APIC
8259A 干的挺不錯的,不過后來咱們廠擴大規模,從單核 CPU 變成了多核,他就有點應付不過來了。
終于有一天,廠里召開會議,把 8259A 給撤了,成立了一個新的全資子公司叫高級可編程中斷控制器 APIC,名字就多了個高級兩個字,干的活還是一樣的。
不過你還別說,這兩個字還真不是吹噓,比 8259A 不知道高到哪里去了。
這個 APIC 的新公司一上臺,就成立了兩個部門,一個叫 I/O APIC,負責接待那些要找我們辦事兒的單位,一個叫 Local APIC,以外包的形式入駐到我 CPU 的各個車間工作,因為就挨著我們辦公,所以取名叫 Local。
I/O APIC 收到中斷信號以后,根據自己的策略就分發到對應的 Local APIC,咱們八個車間就可以專心處理了,為我們省了不少事兒。
不僅如此,通過這個外包團隊,我們 8 個車間還能向彼此發起中斷請求,我們把這個叫做處理器間中斷 Inter-Processor Interrupt,簡稱 IPI。
中斷親和性
每當網絡中有數據包到來,網卡那家伙就發送一個中斷消息過來,告訴我們去處理。
不過最近不知道怎么回事,網絡數據量激增。咱們廠里明明有 8 個車間,他非得一個勁的只給我們發消息,搞得我們手頭的工作老是被打斷,忙得不可開交。
終于,我忍不住了,去找網卡那家伙理論了一番。不過他告訴我,這也不能怪他,分發給誰處理,那是 APIC 在負責。
想想也是,回頭我就去了 APIC 那里,要求他們分攤一點給別的車間處理。
APIC 表示這他們做不了主,得讓廠里來決定。
沒過幾天,廠里開了個會,參會的有各車間代表、APIC 負責人,還請了操作系統那邊的相關代表過來。
會上,大家為了此事爭執不休。
二號車間虎子:“阿 Q,誰叫你們一號車間是 Bootstrap Processor,你們就多辛苦一點嘛”。
三號車間代表:“你這話說的不合適,大家是一個 Team,要互相幫助!要不這樣,既然有這么多單位要聯系我們,咱就分下工,比如一號車間負責網卡,二號負責磁盤,我們三號負責鍵盤,以此類推。”
五號車間代表:“你想的倒是挺美哦,鍵盤一天能發多少中斷,網卡一天要發多少中斷,你凈挑輕松的干。這樣吧,咱就用隨機分發進行負載均衡你們覺得怎么樣?”
八號車間代表:“隨機個啥啊,多麻煩,依我看吶咱 8 個車間就輪流來唄。”
這時,領導問操作系統代表有沒有什么建議。
這代表站起身來,推了推眼鏡說到:“幾位有沒有聽過線程的 CPU 親和性?”
大家都搖了搖頭,問到:“這是個什么意思?”
“就是有些線程想綁定在你們之中的某一個核上面執行,不希望一會兒在這個核執行,一會兒在那個核執行。”
我接過他的話:“好像是有這么回事兒,之前有遇到過,有個線程一直被分配到我們一號車間,不過我們對這個不用關心吧,執行誰不是干活啊,對我們都一個樣。”
代表搖了搖頭,“唉,這可不一樣!你們每個核的一二級緩存都是自己在管理,要是換到別的核,這緩存多半就沒用了,又得重新來建立,這換來換去的豈不是瞎耽誤功夫嘛!對于一般的線程他們倒是不關心,但是有些線程執行大量的內存訪問和運算處理,又對性能要求很高的話,那就很在意這個問題了。”
我們幾個都恍然大悟,紛紛點頭。
虎子起身問到:“那你們是如何實現這個親和性的呢?這跟我們今天的會議又有什么關系呢?”
代表繼續回答說到:“我先回答你的第一個問題。線程調度是我們操作系統完成的工作,我們提供了 API 接口,線程通過調用這些接口表明自己的親和性意愿,我們在調度的時候就能按照他們的意愿把線程分配給你們來執行。”
代表喝了一口水接著說到:“我再回答你的第二個問題。既然線程可以有親和性,那中斷也可以按照這個思路來分發啊!APIC 默認有一套分發策略,但是也提供親和性的設置,可以指定誰哪些核來處理,這樣不用把規矩定死,靈活可變,豈不更好?”
剛說完,會議室門口突然出現一年輕少年,揮手將操作系統代表喚了出去。
接下來,我們詳細討論了這種方案的可行性,最后大家一致決定,就照這么辦。
我們一起提出了一個叫中斷親和性的東西,操作系統那邊提供一個可配置的入口 smp_affinity,可以通過設置各處理器核的掩碼來決定中斷交由誰來處理,APIC 回去負責落地支持。
有了這套方案,再遇到網絡高峰期,咱們一號車間的壓力就有辦法緩解了。
我們剛剛達成一致,操作系統代表返回會議室,神色凝重的說到:“不好意思各位,操作系統那邊有點事情需要趕回去處理一下,先走一步了。”
隨著網卡的一聲中斷,一個新的數據包來到了這片土地。帝國網絡部新來的年輕人顯然沒有意識到危險的到來······
太慢不能忍!CPU 又拿硬盤和網卡開刀了!
總線技術
我是 CPU 一號車間的阿 Q,最近為了一件事兒搞得我挺煩的。
當初我們 CPU 工廠剛剛來到主板上建廠時,那時候主板上的單位還不多,跟我們打交道最多的就是內存那家伙了。
后來,鍵盤、鼠標、硬盤、網卡、聲卡、顯卡等等設備紛紛入駐主板,這塊土地變得越來越熱鬧起來。
不過,他們的到來并沒有影響我們的地位,畢竟我們是中央處理器,所有人都得聽我們指揮。
為了和主板上這些家伙們通信,我們花了重金鋪了一條線路,主板上家家戶戶都連上了這條線路,我們把它叫做總線,雖然說是一條,但實際上它包含了傳輸數據的數據總線,傳輸地址的地址總線和進行控制管理的控制總線。
這樣一來,各單位就能一起聊天了。不過這線路是共用的,大家不能都一起傳數據,那就亂套了。
為了統一管理,我們設立了一個新的單位叫總線控制器,這個單位來統一管理總線,大家要通信就得找它申請,這就叫做總線仲裁。
不過啊,主板上的單位之間的速度還是千差萬別的,像內存就比硬盤、網卡這些單位快多了(當然,跟我們 CPU 車間的工作速度那還是不能比)。
不僅如此,不同單位他們的接口還千差萬別,用一套總線矛盾就日益明顯了,后來就變成了多級總線,讓慢的跟慢的玩,快的跟快的玩,最后大家再用一個東西把不同總線連接起來,這個東西就是橋!
主板上后來出現了兩個著名的橋,一個離我們 CPU 很近的叫北橋,內存那家伙和我們通信就會經過它,另一個離我們遠一點的叫南橋,那些慢一些的 I/O 設備就通過南橋接進來。
再后來,隨著我們 CPU 工廠的壯大,直接把北橋收購了,現在變成了我們廠里的一個部門了。
PIO 模式
現在我們可以和這些 I/O 設備通信了,就拿硬盤來說吧,它有 I/O 端口,我們提供了 in 和 out 兩條指令,就可以對它進行讀寫數據了。
這種通信的方式叫做可編程輸入輸出模型,Programming Input/Output Model,簡稱 PIO。
我們是整個主板上的核心,俗話說得好,能力越大,責任越大,但有時候真心覺得有點累。
隨著越來越多的設備接入主板,越來越多的程序需要等待我們去執行,工作量大的壓的我們喘不過氣來。
尤其是隨著技術進步,我們 CPU 工廠的速度越來越快,與硬盤的讀寫速度之間的差距越來越拉大,我們還用這種方式通信就太浪費我們的時間了。
DMA 技術
這幾天,我們幾個車間的 Leader 私下聚在一起討論起這個事情來。
“阿 Q,你不覺得現在我們花了太多時間再讀寫硬盤上了嗎,這家伙慢不是他的錯,扯我們后腿這就是他的錯了啊。傳輸一次數據,我們要執行好多次 I/O 端口讀寫,我們寶貴的時間都浪費在這上面了!”,二號車間的虎子一臉幽怨的說到。
“嗨,我最近也為這事發愁呢,程序越來越多,讀寫硬盤的時間越來越多了,尤其是那個叫 MySQL 的,老讓我訪問硬盤,可累死我了。”
沒想到我倆都憋了一肚子苦水呢。
這時,平日里愛拍老板馬屁的八號車間老大說了一句話:“你們說的問題確實存在,這工作太沒技術含量了,就是個體力活嘛,要不咱給老板說說,讓他外包出去吧。”
我倆一聽,妙啊,要是能把這體力活外包出去,那可簡直太好了,我們就可以專心做我們的專職工作了。
“你跟老板平時走得近,這事你去說吧”,我給虎子使了個眼色,一起攛掇老八去說這事。
“行,我去就我去”。
還別說,領導立馬就同意了這個想法,畢竟能提高我們的工作效率,他自然是舉雙手歡迎。
沒過多久,就成立了一個外包團隊,獨立出我們廠子,專門來負責這件事。
和我們 CPU 一樣,他們也提供了幾個寄存器,傳輸數據的時候,只需要設置一下這些寄存器的內容,告訴他們要傳輸哪里的數據,從哪到哪,長度是多少,接下來的事情我們就不用操心了,交由他們來完成。
我們就可以騰出功夫做其他事情,等數據傳輸完畢了,他們再用中斷的方式告訴我們,我們直接去處理就好了,省去了讓我們親自去搬運的過程,真是爽的飛起!
后來,我們給這項技術也取了一個名字,叫 Direct Memory Access,直接存儲器訪問,簡稱 DMA,這個外包團隊就是 DMAC,DMA 控制器。
DMA 全面開花
前幾天的月總結會上,領導表揚了老八,說多虧他的建議讓廠里的生產效率大大提升。早知道,當初就不攛掇老八去跟老板提建議了,我自己去。
正想著走神,突然想到了一個問題,這一次我打算抓住機會掙個表現。
“老板,這個 DMA 技術好是好,但現在只能用于硬盤哦。最近網卡那家伙數據包也挺多的,我花了好多時間去把數據包從網卡讀取到內存中,又低效又沒有技術含量,可不可以把這技術推廣到網卡上啊?”,我起身說到。
老板點了點頭,若有所思。
二號車間虎子見狀也起身說到:“老板,除了硬盤和網卡,顯示器也有這個需求。我經常要疲于奔波于把內存數據傳輸到顯示器,也是勞神勞力,建議 DMA 技術也推廣到顯示器呢。”
老板聽完,皺了皺眉頭說到,“這個不同設備之間的差別還是挺大的,沒法通用。難不成我們要為每個設備成立一個外包團隊?這成本有點高啊···”
老板果然還是老板,還是把成本考慮在第一位。
這時,愛拍馬屁的老八又說話了,“老板說的是。我倒是有個建議,這個 DMA 推廣到網卡、顯示器這些單位也可以,不過讓他們自己掏錢來增加 DMAC,按照他們各自不同的需求來做。咱們不能當這冤大頭。”
老板一聽,喜形于色,大聲叫好!
就這樣,很快我們就把這項技術推廣了出去,主板上以網卡、顯示器、攝像頭為首的那些個單位為了不落后于人,紛紛擁抱變化,集成了 DMAC。
我們得到了徹底的解放,再也不用做枯燥的搬運工了~
彩蛋:“阿 Q,聽說了嗎,最近 Linux 帝國新成立了一個公司,居然繞過我們 CPU 就能把數據從網卡寫入硬盤中”。
“不可能啊,至少得經過我們拷貝一下吧”,“根本不用,他們號稱是零拷貝技術”。預知后事如何,請關注后續精彩······
作者:軒轅之風
編輯:陶家龍
出處:轉載自微信公眾號編程技術宇宙(ID:xuanyuancoding)