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