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

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

搞懂Linux的原子操作與同步機制有這一篇文就夠了!

2022-05-11 17:08 作者:補給站Linux內(nèi)核  | 我要投稿

并發(fā)問題

  • 現(xiàn)代操作系統(tǒng)支持多任務(wù)的并發(fā),并發(fā)在提高計算資源利用率的同時也帶來了資源競爭的問題。例如C語言語句“count++;”在未經(jīng)編譯器優(yōu)化時生成的匯編代碼為。



  • 當(dāng)操作系統(tǒng)內(nèi)存在多個進程同時執(zhí)行這段代碼時,就可能帶來并發(fā)問題。



  • 假設(shè)count變量初始值為0。進程1執(zhí)行完“mov eax, [count]”后,寄存器eax內(nèi)保存了count的值0。此時,進程2被調(diào)度執(zhí)行,搶占了進程1的CPU的控制權(quán)。進程2執(zhí)行“count++;”的匯編代碼,將累加后的count值1寫回到內(nèi)存。然后,進程1再次被調(diào)度執(zhí)行,CPU控制權(quán)回到進程1。進程1接著執(zhí)行,計算count的累加值仍為1,寫回到內(nèi)存。雖然進程1和進程2執(zhí)行了兩次“count++;”操作,但是count實際的內(nèi)存值為1,而不是2!

單處理器原子操作

  • 解決這個問題的方法是,將“count++;”語句翻譯為單指令操作。



  • Intel x86指令集支持內(nèi)存操作數(shù)的inc操作,這樣“count++;”操作可以在一條指令內(nèi)完成。因為進程的上下文切換是在總是在一條指令執(zhí)行完成后,所以不會出現(xiàn)上述的并發(fā)問題。對于單處理器來說,一條處理器指令就是一個原子操作。

多處理器原子操作

  • 但是在多處理器的環(huán)境下,例如SMP架構(gòu),這個結(jié)論不再成立。我們知道“inc [count]”指令的執(zhí)行過程分為三步:

  1. 從內(nèi)存將count的數(shù)據(jù)讀取到cpu。

  2. 累加讀取的值。

  3. 將修改的值寫回count內(nèi)存。

  • 這又回到前面并發(fā)問題類似的情況,只不過此時并發(fā)的主題不再是進程,而是處理器。

  • Intel x86指令集提供了指令前綴lock用于鎖定前端串行總線(FSB),保證了指令執(zhí)行時不會受到其他處理器的干擾。



  • 使用lock指令前綴后,處理器間對count內(nèi)存的并發(fā)訪問(讀/寫)被禁止,從而保證了指令的原子性。



【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。?!前100名進群領(lǐng)取,額外贈送一份價值699的內(nèi)核資料包(含視頻教程、電子書、實戰(zhàn)項目及代碼)? ?

x86原子操作實現(xiàn)

Linux的源碼中x86體系結(jié)構(gòu)原子操作的定義文件為。 linux2.6/include/asm-i386/atomic.h 文件內(nèi)定義了原子類型atomic_t,其僅有一個字段counter,用于保存32位的數(shù)據(jù)。

其中原子操作函數(shù)atomic_inc完成自加原子操作。

其中LOCK宏的定義為。

  • 可見,在對稱多處理器架構(gòu)的情況下,LOCK被解釋為指令前綴lock。而對于單處理器架構(gòu),LOCK不包含任何內(nèi)容。

arm原子操作實現(xiàn)

在arm的指令集中,不存在指令前綴lock,那如何完成原子操作呢? Linux的源碼中arm體系結(jié)構(gòu)原子操作的定義文件為。 linux2.6/include/asm-arm/atomic.h 其中自加原子操作由函數(shù)atomic_add_return實現(xiàn)。

上述嵌入式匯編的實際形式為。

ldrex指令將v->counter的值傳送到result,并設(shè)置全局標(biāo)記“Exclusive”。 add指令完成“result+i”的操作,并將加法結(jié)果保存到result。 strex指令首先檢測全局標(biāo)記“Exclusive”是否存在,如果存在,則將result的值寫回counter->v,并將temp置為0,清除“Exclusive”標(biāo)記,否則直接將temp置為1結(jié)束。 teq指令測試temp值是否為0。 bne指令temp不等于0時跳轉(zhuǎn)到標(biāo)號1,其中字符b表示向后跳轉(zhuǎn)。 整體看來,上述匯編代碼一直嘗試完成“v->counter+=i”的操作,直到temp為0時結(jié)束。

  • 使用ldrex和strex指令對是否可以保證add指令的原子性呢?假設(shè)兩個進程并發(fā)執(zhí)行“l(fā)drex+add+strex”操作,當(dāng)進程1執(zhí)行l(wèi)drex后設(shè)定了全局標(biāo)記“Exclusive”。此時切換到進程2,執(zhí)行l(wèi)drex前全局標(biāo)記“Exclusive”已經(jīng)設(shè)定,ldrex執(zhí)行后重復(fù)設(shè)定了該標(biāo)記。然后執(zhí)行add和strex指令,完成累加操作。再次切換回進程1,接著執(zhí)行add指令,當(dāng)執(zhí)行strex指令時,由于“Exclusive”標(biāo)記被進程2清除,因此不執(zhí)行傳送操作,將temp設(shè)置為1。后繼teq指令測定temp不等于0,則跳轉(zhuǎn)到起始位置重新執(zhí)行,最終完成累加操作!可見ldrex和strex指令對可以保證進程間的同步。多處理器的情況與此相同,因為arm的原子操作只關(guān)心“Exclusive”標(biāo)記,而不在乎前端串行總線是否加鎖。

  • 在ARMv6之前,swp指令就是通過鎖定總線的方式完成原子的數(shù)據(jù)交換,但是影響系統(tǒng)性能。ARMv6之后,一般使用ldrex和strex指令對代替swp指令的功能。

自旋鎖中的原子操作

Linux的源碼中x86體系結(jié)構(gòu)自旋鎖的定義文件為。 linux2.6/include/asm-i386/spinlock.h 其中__raw_spin_lock完成自旋鎖的加鎖功能

上述代碼的實際匯編形式為。

其中l(wèi)ock->slock字段初始值為1,執(zhí)行原子操作decb后值為0。符號位為0,執(zhí)行jns指令跳轉(zhuǎn)到3,完成自旋鎖的加鎖。 當(dāng)再次申請自旋鎖時,執(zhí)行原子操作decb后lock->slock值為-1。符號位為1,不執(zhí)行jns指令。進入標(biāo)簽2,執(zhí)行一組nop指令后比較lock->slock是否小于等于0,如果小于等于0回到標(biāo)簽2進行循環(huán)(自旋)。否則跳轉(zhuǎn)到標(biāo)簽1重新申請自旋鎖,直到申請成功。 自旋鎖釋放時會將lock->slock設(shè)置為1,這樣保證了其他進程可以獲得自旋鎖。

信號量中的原子操作

Linux的源碼中x86體系結(jié)構(gòu)信號量的定義文件為。 linux2.6/include/asm-i386/semaphore.h 信號量的申請操作由函數(shù)down實現(xiàn)。

實際的匯編代碼形式為。

信號量的sem->count一般初始化為一個正整數(shù),申請信號量時執(zhí)行原子操作decl,將sem->count減1。如果該值減為負數(shù)(符號位為1)則跳轉(zhuǎn)到另一個段內(nèi)的標(biāo)簽2,否則申請信號量成功。 標(biāo)簽2被編譯到另一個段內(nèi),進入標(biāo)簽2后,執(zhí)行l(wèi)ea指令取出sem->count的地址,放到eax寄存器作為參數(shù),然后調(diào)用函數(shù)__down_failed表示信號量申請失敗,進程加入等待隊列。最后跳回標(biāo)簽1結(jié)束信號量申請。 信號量的釋放操作由函數(shù)up實現(xiàn)。

實際的匯編代碼形式為。

釋放信號量時執(zhí)行原子操作incl將sem->count加1,如果該值小于等于0,則說明等待隊列有阻塞的進程需要喚醒,跳轉(zhuǎn)到標(biāo)簽2,否則信號量釋放成功。 標(biāo)簽2被編譯到另一個段內(nèi),進入標(biāo)簽2后,執(zhí)行l(wèi)ea指令取出sem->count的地址,放到eax寄存器作為參數(shù),然后調(diào)用函數(shù)__up_wakeup喚醒等待隊列的進程。最后跳回標(biāo)簽1結(jié)束信號量釋放。

總結(jié)

  • 本文通過對操作系統(tǒng)并發(fā)問題的討論研究操作系統(tǒng)內(nèi)的原子操作的實現(xiàn)原理,并討論了不同體系結(jié)構(gòu)下Linux原子操作的實現(xiàn),最后描述了Linux操作系統(tǒng)如何利用原子操作實現(xiàn)常見的進程同步機制,希望對你有所幫助。


搞懂Linux的原子操作與同步機制有這一篇文就夠了!的評論 (共 條)

分享到微博請遵守國家法律
遂宁市| 新余市| 汤阴县| 治县。| 深水埗区| 汉寿县| 会泽县| 汽车| 西和县| 文昌市| 梅州市| 揭东县| 广宁县| 巴楚县| 红安县| 横峰县| 全椒县| 上饶市| 铜山县| 枣强县| 册亨县| 璧山县| 襄樊市| 舒城县| 潞城市| 英吉沙县| 淮北市| 三河市| 闵行区| 抚远县| 新晃| 东海县| 河东区| 嫩江县| 兰州市| 手游| 罗定市| 镇江市| 巩留县| 宁夏| 乐陵市|