內(nèi)核系統(tǒng)調(diào)用的實(shí)現(xiàn)和互斥機(jī)制
本文轉(zhuǎn)載自微信公眾號(hào)「編程雜技」,作者theanarkh。轉(zhuǎn)載本文請(qǐng)聯(lián)系編程雜技公眾號(hào)。
有感于最近在知乎看到了兩個(gè)問題,分享一下對(duì)內(nèi)核系統(tǒng)調(diào)用的實(shí)現(xiàn)和互斥機(jī)制的認(rèn)識(shí)。
下面是這兩個(gè)問題:
https://www.zhihu.com/question/462048846/answer/1919407185
https://www.zhihu.com/question/460985657/answer/1912146181
系統(tǒng)調(diào)用的實(shí)現(xiàn)
兩個(gè)問題分別是問了TCP/IP協(xié)議和epoll的實(shí)現(xiàn)中,內(nèi)核是否使用了多線程。這個(gè)問題的角度挺有意思的,內(nèi)核雖然在內(nèi)部使用進(jìn)程/線程實(shí)現(xiàn)了某些功能(比如pdflush線程定時(shí)回寫硬盤、kswapd進(jìn)程周期回收內(nèi)存、處理工作隊(duì)列的線程)。但是系統(tǒng)調(diào)用的實(shí)現(xiàn)中,是不涉及多線程的概念的。
操作系統(tǒng)本質(zhì)上是對(duì)底層的資源進(jìn)行管理并封裝了底層的能力,對(duì)上層提供服務(wù)。這種服務(wù)好比是實(shí)現(xiàn)了一個(gè)排序算法,但是是否使用多線程,這個(gè)是由上層決定的,內(nèi)核本身不會(huì)在底層實(shí)現(xiàn)多線程排序這種能力。
互斥機(jī)制
但是因?yàn)樵诙嗪说那闆r下,多個(gè)CPU上會(huì)執(zhí)行多個(gè)線程,如果多個(gè)線程同時(shí)請(qǐng)求內(nèi)核訪問同一個(gè)內(nèi)核數(shù)據(jù)結(jié)構(gòu),那么就會(huì)引起競(jìng)態(tài)情況。所以內(nèi)核需要實(shí)現(xiàn)訪問資源的互斥機(jī)制。這樣才能保證多個(gè)CPU中同時(shí)只有一個(gè)CPU會(huì)操作共享的數(shù)據(jù)結(jié)構(gòu)。比如自旋鎖,保證多個(gè)CPU只有其中一個(gè)CPU拿到這個(gè)鎖,然后操作共享的數(shù)據(jù)。另外,內(nèi)核還實(shí)現(xiàn)了原子操作,比如內(nèi)核里提供的atomic原子操作,可以對(duì)整形變量進(jìn)行原子性操作,其具體實(shí)現(xiàn)原理根據(jù)CPU架構(gòu)而不同,比如i386 CPU提供了Lock指令,保證同時(shí)只有一個(gè)CPU可以鎖住總線,對(duì)內(nèi)存進(jìn)行互斥訪問,下面是i386原子操作的實(shí)現(xiàn)。
- static __inline__ void atomic_add(int i, atomic_t *v)
- {
- __asm__ __volatile__(
- LOCK "addl %1,%0"
- // 輸出到v->counter所在內(nèi)存
- :"=m" (v->counter)
- // %1和0%對(duì)應(yīng)下面兩個(gè)值,i是整形,隨便存到一個(gè)寄存器,m表示表示從v->counter的內(nèi)存讀取
- :"ir" (i), "m" (v->counter));
- }
如果單核的情況下,非搶占式的則不需要這種機(jī)制,因?yàn)樵趫?zhí)行系統(tǒng)調(diào)用的時(shí)候,進(jìn)程調(diào)度器是不會(huì)調(diào)度其他進(jìn)程執(zhí)行的,這就保證了系統(tǒng)調(diào)用的原子性。如果在搶占式模式下并且支持在執(zhí)行系統(tǒng)調(diào)用時(shí)被搶占,那么還是需要互斥和原子機(jī)制的,總而言之,存在競(jìng)態(tài)情況的,都需要保證共享數(shù)據(jù)的互斥訪問。
內(nèi)核實(shí)現(xiàn)的功能雖然沒有使用多線程,但是通常底層是多核,上層是使用多進(jìn)程/多線程的,所以內(nèi)核為了保證互斥訪問共享數(shù)據(jù),需要實(shí)現(xiàn)一些原子操作和互斥機(jī)制。