除零中断是什么意思?_百万并发「零拷贝」技术系列之初探门径
Wiki對零拷貝的定義
"Zero-copy" describes computer operations in which the CPU does not perform the task of copying data from one memory area to another.
零拷貝(Zero-copy)是指在計(jì)算機(jī)執(zhí)行操作時,CPU 不需要將數(shù)據(jù)從一塊內(nèi)存拷貝到另一塊內(nèi)存,減少拷貝次數(shù)可以提高性能。
在操作系統(tǒng)層面來說零拷貝是指不需要將數(shù)據(jù)從內(nèi)核空間復(fù)制到用戶空間,而Netty、Kafka等框架都因零拷貝而聞名著稱,技術(shù)來不得半點(diǎn)馬虎和一知半解,本著知其然知其所以然的態(tài)度,本系列為你揭秘其中原委和解決方案。
計(jì)算機(jī)組成
計(jì)算機(jī)是由硬件、內(nèi)核和上層應(yīng)用組成,通過它們在功能上由下而上的層層傳遞給用戶提供各種服務(wù),如下圖所示。為了便于獨(dú)立開發(fā)、調(diào)試和維護(hù),采用了高內(nèi)聚低耦合分層設(shè)計(jì)思想:內(nèi)核負(fù)責(zé)對硬件直接操作,在封裝硬件操作的同時給上層應(yīng)用提供功能接口,承上啟下;上層應(yīng)用調(diào)用內(nèi)核接口為用戶提供業(yè)務(wù)服務(wù)。每一層都使用較低層提供的功能而不必知道其實(shí)現(xiàn)細(xì)節(jié),只需了解其接口能做什么即可。
實(shí)際上隨著時間的演進(jìn)和功能的不斷豐富,內(nèi)核體積變得龐大不易管理,所以現(xiàn)代的操作系統(tǒng)基本都采用微內(nèi)核的設(shè)計(jì)思想:把內(nèi)核模塊化,將非基礎(chǔ)模塊從內(nèi)核中移除,把這些非基礎(chǔ)模塊實(shí)現(xiàn)為系統(tǒng)應(yīng)用,甚至用戶應(yīng)用,從而減少內(nèi)核的體積和復(fù)雜度,使其功能更聚焦。
微內(nèi)核設(shè)計(jì)的好處頗多:
然而微內(nèi)核究竟包括哪些基礎(chǔ)模塊,實(shí)際上每個操作系統(tǒng)的處理并不相同,并沒有定論和標(biāo)準(zhǔn),但一般至少會包括進(jìn)程、內(nèi)存管理和通訊功能。
上層應(yīng)用包含了系統(tǒng)應(yīng)用和用戶應(yīng)用:系統(tǒng)應(yīng)用一般跟隨系統(tǒng)發(fā)行版而來,但也是通過調(diào)用內(nèi)核接口開發(fā)的,一般是用于系統(tǒng)管理;用戶應(yīng)用是用戶自行開發(fā)的應(yīng)用,一般是為了實(shí)現(xiàn)自己的業(yè)務(wù)邏輯。但上層應(yīng)用一般都采用高級語言來編寫,為了降低復(fù)雜性和高效,高級語言對內(nèi)核接口進(jìn)行了封裝,提供了編程語言類庫,比如C語言的標(biāo)準(zhǔn)庫、Java的JDK等。
用戶空間和內(nèi)核空間
用戶進(jìn)程不能直接操作硬件,只有通過內(nèi)核提供的接口來操作,而為了確保內(nèi)核的正常、安全地運(yùn)行,不會因上層應(yīng)用的異常導(dǎo)致內(nèi)核陷入災(zāi)難,就必須區(qū)分內(nèi)核代碼執(zhí)行和用戶定義代碼執(zhí)行,也就是所謂的雙重模式即:內(nèi)核態(tài)和用戶態(tài)。當(dāng)用戶程序正在執(zhí)行,系統(tǒng)處于用戶態(tài),當(dāng)用戶程序需要調(diào)用內(nèi)核功能,它必須通過系統(tǒng)調(diào)用的形式轉(zhuǎn)換為內(nèi)核態(tài)執(zhí)行。一般是通過硬件支持來區(qū)分兩種模式的,在硬件中增加了一個模式bit位:0代表內(nèi)核態(tài),1代表用戶態(tài)。
系統(tǒng)通過引導(dǎo)程序,裝入內(nèi)核處于內(nèi)核態(tài),緊接著開始執(zhí)行用戶進(jìn)程進(jìn)入用戶態(tài)(模式位為1),一旦遇到中斷或系統(tǒng)調(diào)用,則又從用戶態(tài)進(jìn)入內(nèi)核態(tài)(模式位為0),內(nèi)核處理完后返回用戶進(jìn)程進(jìn)入用戶態(tài)(模式位為1),如上圖。
進(jìn)程是操作系統(tǒng)資源分配的最小單元,進(jìn)程在執(zhí)行上有用戶態(tài)和內(nèi)核態(tài),那么虛擬內(nèi)存也分為了用戶空間和內(nèi)核空間,供用戶態(tài)和內(nèi)核態(tài)的進(jìn)程使用。比如32位的操作系統(tǒng)內(nèi)存可以高達(dá)4G,把最高的1G字節(jié)(虛擬內(nèi)存地址0xC0000000~0xFFFFFFFF)供內(nèi)核使用,稱為內(nèi)核空間,而將較低的3G字節(jié)(虛擬內(nèi)存地址 從0x00000000到0xBFFFFFFF)供上層應(yīng)用使用,稱為用戶空間。
虛擬內(nèi)存是相對于物理內(nèi)存而言,操作系統(tǒng)會對物理內(nèi)存進(jìn)行映射和抽象,軟件的所有操作都是對虛擬內(nèi)存而言,也可以理解為物理內(nèi)存映射為用戶空間和內(nèi)核空間。
當(dāng)進(jìn)程由用戶態(tài)進(jìn)行進(jìn)入內(nèi)核態(tài),系統(tǒng)需要保存當(dāng)前運(yùn)行在CPU中進(jìn)程的上下文,從而能在其處理完畢后轉(zhuǎn)換為用戶態(tài)時能恢復(fù)其上下文,這一任務(wù)稱為上下文切換(context switch)。上下文切換在計(jì)算機(jī)執(zhí)行期間會比較頻繁,只要牽涉到內(nèi)核態(tài)和用戶態(tài)的轉(zhuǎn)換就會涉及到上下文切換。所謂的上下文究竟是指什么呢?上下文從其英文context可知,是進(jìn)行運(yùn)行的環(huán)境,它包括進(jìn)程的狀態(tài)、計(jì)數(shù)器、全局變量、臨時數(shù)據(jù)如函數(shù)參數(shù)、返回地址、局部變量等,還可能包括運(yùn)行期間動態(tài)分配的內(nèi)存堆(heap)。頻繁的上下文切換,對數(shù)據(jù)的保存和恢復(fù)操作過于頻繁,對性能的影響特別顯著。
示例
為了全面理解用戶空間、內(nèi)核空間、用戶態(tài)、內(nèi)核態(tài),我們舉個例子來說明:讀取文件內(nèi)容并通過Socket發(fā)送。
由于用戶進(jìn)程無法直接操作硬件,因此用戶進(jìn)程首先需要通過系統(tǒng)調(diào)用(System Call)來調(diào)用內(nèi)核接口,此時的事件流如下
由上圖流程可知會經(jīng)歷4次上下文切換,而它的數(shù)據(jù)會也經(jīng)歷了4次拷貝,數(shù)據(jù)流向如下
什么是DMA
所有的硬件是通過控制器連接到計(jì)算機(jī)總總線,傳統(tǒng)的中斷式I/O方式是把數(shù)據(jù)拷貝到控制器寄存器,控制器再以中斷的方式通知CPU拷貝到內(nèi)存。由于這種方式頻繁的中斷,導(dǎo)致大量占用CPU時間片。DMA是Direct Memory Access的縮寫,中文稱之為直接存儲器訪問。它的使用方式是CPU通知DMA控制器進(jìn)行I/O后CPU就被解脫出來做別的事情了,數(shù)據(jù)的拷貝過程都是由DMA來操作完成,數(shù)據(jù)拷貝完成后DMA控制器以中斷的方式通知CPU。
寫在最后
本篇我們了解了用戶態(tài)、內(nèi)核態(tài)、用戶空間、內(nèi)核空間的概念,而且從事件流和數(shù)據(jù)流我們也找到了提高性能的優(yōu)化方向:降低拷貝和上下文切換次數(shù),下一篇我們將揭曉優(yōu)化方案。
相關(guān)閱讀
緩存穿透、緩存擊穿、緩存雪崩看這篇就夠了
一口氣講透一致性哈希(Hash),助力「碼農(nóng)變身」
漫畫 | 架構(gòu)設(shè)計(jì)中的那些事
Java中異常處理的9個最佳實(shí)踐
Intellij IDEA必備插件,提高效率的“七種武器”
接住嘍,送你個裝B的技能:JDK動態(tài)代理
給“小白”漫畫+圖示講解MyBatis原理,就問香不香
總結(jié)
以上是生活随笔為你收集整理的除零中断是什么意思?_百万并发「零拷贝」技术系列之初探门径的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: eclipse lombok插件安装_便
- 下一篇: goland go test_Go单元测