最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Kernel同步機制的底層實現(xiàn)(超詳細(xì)~)

2022-07-27 14:38 作者:補給站Linux內(nèi)核  | 我要投稿


原子操作

通常我們代碼中的a = a + 1這樣的一行語句,翻譯成匯編后蘊含著3條指令:

即?

(1)從內(nèi)存中讀取a變量到X0寄存器?

? (2)X0寄存器加1?

(3)將X0寫入到內(nèi)存a中

既然是3條指令,那么就有可能并發(fā),也就意味著返回的結(jié)果可能不是預(yù)期的。

然后在linux kernel的操作系統(tǒng)中,提供訪問原子變量的函數(shù),用來解決上述問題。其中部分原子操作的API如下:

atomic_read atomic_add_return(i,v)?

atomic_add(i,v)?

atomic_inc(v)?

atomic_add_unless(v,a,u)?

atomic_inc_not_zero(v)?

atomic_sub_return(i,v)?

atomic_sub_and_test(i,v)?

atomic_sub(i,v)?

atomic_dec(v)?

atomic_cmpxchg(v,舊,新)

那么操作系統(tǒng)(僅僅是軟件而已)是如何保證原子操作的呢?(還是得靠硬件),硬件原理是什么呢?

以上的那些API函數(shù),在底層調(diào)用的其實都是如下__lse_atomic_add_return##name宏的封裝,這段代碼中最核心的也就是ldadd指令了,這是armv8.1增加的LSE(Large System Extension)feature。

那么系統(tǒng)如果沒有LSE擴展呢,即armv8.0,其實現(xiàn)的原型如下所示,這段代碼中最核心的也就是ldxr、stxr指令了。

那么在armv8.0之前呢,如armv7是怎樣實現(xiàn)的?如下所示, 這段代碼中最核心的也就是ldrex、strex指令了。

總結(jié):

在很早期,使用arm的exclusive機制來實現(xiàn)的原子操作,exclusive相關(guān)的指令也就是ldrex、strex了,但在armv8后,exclusive機制的指令發(fā)生了變化變成了ldxr、stxr。但是又由于在一個大系統(tǒng)中,處理器是非常多的,競爭也激烈,使用獨占的存儲和加載指令可能要多次嘗試才能成功,性能也就變得很差,在armv8.1為了解決該問題,增加了ldadd等相關(guān)的原子操作指令。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實戰(zhàn)項目及代碼)? ? ? ?


早期旋鎖的設(shè)計

早期的spinlock的設(shè)計是鎖的擁有者加鎖時將鎖的值設(shè)置為1,釋放鎖時將鎖的值設(shè)置為0,這樣做的缺點是會出現(xiàn) 先來搶占鎖的進(jìn)程一直搶占不到鎖,而后來的進(jìn)程可能一來 就能獲取到鎖。導(dǎo)致這個原因的是先搶占的進(jìn)程和后搶占的進(jìn)程在搶占鎖時并沒有一個先后關(guān)系,最終就是離鎖所在的內(nèi)存最近的cpu節(jié)點就有更多的機會搶占鎖,離鎖所在內(nèi)存遠(yuǎn)的節(jié)點可能一直搶占不到。

新版旋鎖設(shè)計

為了解決這個spinlock的不公平問題,linux 2.6.25內(nèi)核以后,spinlock采用了一種“FIFO ticket-based”算法的spinlock機制,可以很好的實現(xiàn)先來先搶占的思想。具體的做法如下:

  1. spinlock的核心字段有owner和next,在初始時,owner=next=0

  2. 當(dāng)?shù)谝粋€進(jìn)程搶占spinlock時,會在進(jìn)程函數(shù)本地保存下next的值,也就是next=0,并將spinlock的next字段加1;

  3. 當(dāng)獲取spinlock的進(jìn)程的本地next和spinlock的owner相等時,該進(jìn)程就獲取到spinlock;

  4. 由于第一個進(jìn)程本地的next=0,并且spinlock的owner為0,所以第一個CPU獲取到spinlock;

  5. 接著當(dāng)?shù)诙€進(jìn)程搶占spinlock,此時spinlock的next值為1,保存到本地,然后將spinlock的next字段加1。而spinlock的owner字段依然為0,第二個進(jìn)程的本地next 不等于spinlock的owner,所以一直自旋等待spinlock;

  6. 第三個進(jìn)程搶占spinlock,得到本地next值為2,然后將spinlock的next字段加1。此時spinlock的owner字段還是為0,所以第三個進(jìn)程自旋等待。

  7. 當(dāng)?shù)谝粋€進(jìn)程處理完臨界區(qū)以后,就釋放spinlock,執(zhí)行的操作是將spinlock的owner字段加1;

  8. 由于第二個進(jìn)程和第三個進(jìn)程都還在等待spinlock,他們會不停第獲取spinlock的owner字段,并和自己本地的next值進(jìn)行比較。當(dāng)?shù)诙€進(jìn)程發(fā)現(xiàn)自己的next值和spinlock的owner字段相等時(此時next == owner == 2),第二個進(jìn)程就獲取到spinlock。第三個進(jìn)程的本地next值是3,和spinlock的owner字段不相等,所以繼續(xù)等待;

  9. 只有在第二個進(jìn)程釋放了spinlock,就會將spinlock的owner字段加1,第三個進(jìn)程才有機會獲取spinlock。

我在舉個例子,如下:


T1 : 進(jìn)程1調(diào)用spin_lock,此時next=0, owner=0獲得該鎖,在arch_spin_lock()底層實現(xiàn)中,會next++?

T2 : 進(jìn)程2調(diào)用spin_lock,此時next=1, owner=0沒有獲得該鎖,while(1)中調(diào)用wfe指令standby在那里,等待owner==next成立.?

T3 : 進(jìn)程3調(diào)用spin_lock,此時next=2, owner=0沒有獲得該鎖,while(1)中調(diào)用wfe指令standby在那里,等待owner==next成立.?

T4&T5 : 進(jìn)程1調(diào)用spin_unlock,此時owner++,即owner=1,接著調(diào)用sev指令,讓進(jìn)程2和進(jìn)程3退出standby狀態(tài),走while(1)流程,重新檢查owner==next條件。此時進(jìn)程2條件成立,進(jìn)程3繼續(xù)等待。進(jìn)程2獲得該鎖,進(jìn)程3繼續(xù)等待。

Linux Kernel中的SpinLock的實現(xiàn)

對于arch_spin_lock()、arch_spin_unlock()的底層實現(xiàn),不同的kernel版本也一直在變化。

對于kernel4.4這個版本,還是比較好理解的,最核心的也就是ldaxr、ldaxr獨占指令 ,以及stlrh release指令




Kernel同步機制的底層實現(xiàn)(超詳細(xì)~)的評論 (共 條)

分享到微博請遵守國家法律
石门县| 双辽市| 聂荣县| 丰原市| 宁远县| 卢氏县| 上高县| 鄢陵县| 义乌市| 西丰县| 新干县| 浮山县| 铁力市| 武强县| 二连浩特市| 白山市| 望城县| 林口县| 宁津县| 石渠县| 塔河县| 武功县| 云南省| 中江县| 广水市| 安新县| 中宁县| 昭通市| 布拖县| 清新县| 江城| 普定县| 益阳市| 普宁市| 应用必备| 深水埗区| 南部县| 桐庐县| 元谋县| 铁岭县| 花莲市|