世界頭條:Linux內(nèi)核同步機制原子操作詳解
Linux內(nèi)核同步機制原子操作
變量的修改
我們平時的編程中可能經(jīng)常需要修改變量和寄存器,大概是這樣操作的:
讀一個位于memory中的變量的值然后寫到寄存器中修改該變量的值將寄存器中的值寫回memory中的變量值 如果這三個步驟是串行化的,并且是在一個線程中串行執(zhí)行,那么這樣做是沒有問題的,然而,世界中的事情總是不能如你所愿。在多CPU體系架構(gòu)中,運行在兩個CPU上的兩個內(nèi)核控制路徑同時并行執(zhí)行上面操作序列,有可能發(fā)生下面的場景:CPU和內(nèi)存是通過總線進行互聯(lián)的,在任意時刻,只能有一個CPU訪問內(nèi)存。因此,來自兩個CPU上的讀內(nèi)存操作被串行化執(zhí)行,分別獲得了同樣的舊值。完成修改后,兩個CPU都想進行寫操作,把修改之后的值寫回到內(nèi)存。但是,CPU的寫回操作也必須是串行化的,因此CPU1首先獲得了訪問權(quán),進行寫回動作,隨后,CPU2完成寫回動作。在這種情況下,CPU1的對內(nèi)存的修改被CPU2的寫操作覆蓋了,因此執(zhí)行結(jié)果是錯誤的。
不僅是多CPU會存在這種問題,在單CPU上也會由于內(nèi)核控制路徑的交錯導致上面的錯誤。一個簡單的例子就是中斷:
(相關(guān)資料圖)
系統(tǒng)調(diào)用的控制路徑上,完成讀操作之后,硬件觸發(fā)中斷,開始執(zhí)行中斷處理函數(shù)。中斷處理函數(shù)的寫回操作被系統(tǒng)調(diào)用控制路徑上的寫回操作覆蓋了,導致結(jié)果不一致。
正確的操作
對于那些有多個內(nèi)核控制路徑進行讀-修改-寫回的變量,內(nèi)核提供了一個特殊的類型atomic_t,具體定義如下:
typedef struct { int counter;} atomic_t;
從定義上來看,atomic_t實際上就是一個int類型的變量counter,內(nèi)核中定義了很多關(guān)于atomic_xxx的接口函數(shù),這些函數(shù)只會接收atomic_t類型的參數(shù)。這樣就確保了atomic_xxx的函數(shù)只會操作atomic_t類型的數(shù)據(jù)。
內(nèi)核中具體的接口API函數(shù)如下:
接口函數(shù) | 功能描述 |
---|---|
staticinline void atomic_add(int i, atomic_t *v) | 原子變量v增加i |
static inline void atomic_sub(int i, atomic_t *v) | 原子變量v減去i |
static inline void atomic_inc(atomic_t *v) | 原子變量增加1 |
static inline void atomic_dec(atomic_t *v) | 原子變量減去1 |
static inline int atomic_read(const atomic_t *v) | 讀取原子變量的值 |
static inline void atomic_set(atomic_t *v, int i) | 設(shè)置原子變量的值 |
static inline int atomic_dec_and_test(atomic_t *v) | 原子變量的值減去1,判斷原子變量的值是否等于0 |
static inline int atomic_cmpxchg(atomic_t *v, int oldval, int newval) | 比較oldval的值和原子變量v的值是否相等,如果相等,把newval的值賦值給原子變量v |
底層實現(xiàn)原理
ARMv6之前的CPU并不支持SMP架構(gòu),之后的ARM架構(gòu)都是支持SMP架構(gòu)的。內(nèi)核中關(guān)于原子操作的實現(xiàn)通過#if __LINUX_ARM_ARCH__ >= 6
條件變量進行區(qū)分。ARMv6之前的實現(xiàn)原理是通過關(guān)閉CPU中斷實現(xiàn)的,ARMv6之后的實現(xiàn)是通過新增加的兩個CPU指令ldrex、strex
實現(xiàn)的。 通過下面的代碼可以具體的看到實現(xiàn)的細節(jié):
prefetchhw
是預取操作和cache有關(guān),主要是為了提高性能。__volatile__
主要是用來防止編譯器優(yōu)化的。在編譯c代碼的時候,如果使用優(yōu)化選項(-O)進行編譯,對于那些沒有聲明__volatile__
的嵌入式匯編代碼,編譯器有可能會對其進行編譯優(yōu)化,編譯的結(jié)果可能不是原來的匯編代碼,有了__volatile__
之后,編譯器就會停止對該段代碼的任何優(yōu)化。
獨占訪問指令ldrex和strex
ldrex/strex是ARMv6架構(gòu)及之后架構(gòu)的同步原語,屬于硬件層面的同步機制。只要某個時刻只允許一個執(zhí)行單元訪問共享資源那么就必須進行同步,共享資源可以是內(nèi)存、外設(shè)設(shè)備,執(zhí)行單元可以是處理器、進程或者線程。
ldrex/strex這兩個指令配合獨占監(jiān)控器(獨占監(jiān)控器會跟蹤獨占內(nèi)存訪問)可以實現(xiàn)原子地更新內(nèi)存數(shù)據(jù)。
ldrex R1, [R0]ldrex指令從R0寄存器表示的地址中讀取一個字,存放在R1寄存器中,并且更新獨占監(jiān)控器狀態(tài)為獨占狀態(tài)
strex < Rd >, < Rt >, [< Rn >]strex指令存儲一個字到內(nèi)存中,但是這個存儲指令是有條件的,如果獨占監(jiān)控器允許這個存儲操作,那么對應(yīng)的內(nèi)存地址就會更新,并且將返回值0保存在目標寄存器中,代表此次操作成功。如果獨占監(jiān)控器不允許存儲操作,那么就不會更新獨占監(jiān)控器,并且將返回值1保存在目標寄存器中,代表此次操作失敗。
獨占監(jiān)控器
在上面的描述中我們提到獨占監(jiān)控器,獨占監(jiān)控器是一種簡單的狀態(tài)機,有兩種狀態(tài):打開或者獨占。為了實現(xiàn)多個處理器間的同步,一般會存在兩類獨占監(jiān)控器:本地監(jiān)控器和全局監(jiān)控器。
"1: ldrex %0, [%3]\\n"
其中%3
就是input operand list
中的"r" (&v->counter
),r是限制符(constraint
),用來告訴編譯器gcc
,選擇一個通用寄存器保存該操作數(shù)。%0
對應(yīng)output openrand list
中的"=&r" (result
),=
表示該操作數(shù)是write only
的,&表示該操作數(shù)是一個earlyclobber operand
,編譯器在處理嵌入式匯編的時候,傾向于使用盡可能少的寄存器,如果output operand
沒有&修飾的話,匯編指令中的input
和output
操作數(shù)會使用同一個寄存器。&確保了%3
和%0
使用不同的寄存器?,F(xiàn)在%0
這個output
操作數(shù)已經(jīng)被賦值為atomic_t
變量的old value
,毫無疑問,這里的操作是要給old value
加上i
。這里%4
對應(yīng)"Ir" (i
),這里“I”表示這是一個有特定限制的立即數(shù),該數(shù)必須是0~255之間的一個整數(shù)通過rotation
的操作得到的一個32bit的立即數(shù)。每個指令32個bit,其中12個bit被用來表示立即數(shù),其中8個bit是真正的數(shù)據(jù),4個bit用來表示如何rotation
。這一步將修改后的new value
保存在atomic_t
變量中。是否能夠正確操作的狀態(tài)標記保存在%1
操作數(shù)中,也就是"=&r" (tmp
)。最后檢查memory update
的操作是否正確完成,如果發(fā)生了問題,需要跳轉(zhuǎn)到lable 1
那里,重新進行一次read-modify-write
的操作。
#define ATOMIC_OP(op, c_op, asm_op) \\static inline void atomic_##op(int i, atomic_t *v) \\{ \\ unsigned long tmp; \\ int result; \\ \\ prefetchw(&v- >counter); \\ __asm__ __volatile__("@ atomic_" #op "\\n" \\"1: ldrex %0, [%3]\\n" \\" " #asm_op " %0, %0, %4\\n" \\" strex %1, %0, [%3]\\n" \\" teq %1, #0\\n" \\" bne 1b" \\ : "=&r" (result), "=&r" (tmp), "+Qo" (v- >counter) \\ : "r" (&v- >counter), "Ir" (i) \\ : "cc"); \\}
#define ATOMIC_OP(op, c_op, asm_op) \\static inline void atomic_##op(int i, atomic_t *v) \\{ \\ unsigned long flags; \\ \\ raw_local_irq_save(flags); \\ v- >counter c_op i; \\ raw_local_irq_restore(flags); \\}
總結(jié)
本篇主要介紹了Linux內(nèi)核的同步機制之一原子操作,從原子的操作的API接口到原子操作的底層實現(xiàn)原理,進行了簡單分析。
關(guān)鍵詞:
- 世界頭條:Linux內(nèi)核同步機制原子操作詳解(2023-06-27 02:20:07)
- 長沙:擬用住房公積金增值收益約4.35億購買1100余套公租房|世界簡訊(2023-06-27 02:25:51)
- 世界速看:“花式”降價背后,云廠商的“拉新”陽謀(2023-06-27 02:25:22)
- 奢侈品一年賣出200億,中國國貿(mào)能否走出東三環(huán)? 精選(2023-06-27 02:36:02)
- 荊芥,見證河南人的夏天(2023-06-27 02:21:49)
- 天津市將舉辦“投資中國年”專場活動(2023-06-27 02:26:15)
- 哈爾斯:與浙江大學就智能水杯研發(fā)事宜達成合作(2023-06-27 02:39:54)
- 基金投顧迎重磅新規(guī):鼓勵長期投資 控制組合策略換手率(2023-06-27 02:23:23)
- 環(huán)球即時:更換車牌照怎么辦理(2023-06-27 02:19:52)
- 總投資15億元!又有兩大電池項目落地!_全球消息(2023-06-27 02:22:27)
- 《華納大亂斗》結(jié)束公測 將禁用在線功能直至2024年正式發(fā)售_全球速讀(2023-06-27 02:21:37)
- 安陽滑縣:著力“三聚焦” 提升公共資源交易營商環(huán)境 天天快看(2023-06-27 02:18:10)
- GGII:5月國內(nèi)動力電池裝機量約27GWh 同比增長77%(2023-06-27 02:30:32)
- 龍之谷pk職業(yè)推薦_龍之谷pk最強(2023-06-27 02:35:43)
- 中電控股:藍凌志將卸任CEO,蔣東強今年10月起接任(2023-06-27 02:33:41)
- 背后的溫柔第二部(背后的溫柔)_環(huán)球快播報(2023-06-27 02:17:55)
- 中央氣象臺:我國近海海域?qū)⒂?-7級風(2023-06-27 02:18:27)
- 動態(tài):6月26日常熟鴻嘉氟冰晶石價格平穩(wěn)(2023-06-27 02:20:50)
- 原TES三C重聚?369、Knight、Jackeylove組隊出征亞運會(2023-06-27 02:24:46)
- 凱宏投觀:各國央行應(yīng)向新興市場學習決策經(jīng)驗_每日快訊(2023-06-27 02:20:18)
- 快看:81歲創(chuàng)始人二闖IPO,大股東卻“臨陣撤退”!(2023-06-27 02:28:05)
- 環(huán)球新消息丨V觀財報|電科院創(chuàng)始人胡德霖因病去世,此前陷“父子內(nèi)斗”(2023-06-27 02:33:55)
- 安逸花逾期半年沒還怎么辦?有過逾期全部還完以后還能用嗎? 最新資訊(2023-06-27 02:26:11)
- 世界快看:濱海新區(qū)又添全國榮譽(2023-06-27 02:25:51)
- 豪宅稅廣州(豪宅稅)(2023-06-27 02:36:36)
- 海圖科技任命姚俊俊、謝國龍為公司副總經(jīng)理2022年公司凈利2150.41萬(2023-06-27 02:17:06)
- 市場流動性周報(2023-06-27 02:27:03)
- 環(huán)球熱門:【當前熱聞】觀察丨小龍蝦的“中場戰(zhàn)事” 新消息(2023-06-27 02:23:38)
- 環(huán)球微資訊!賭博(2023-06-27 02:21:11)
- 天天熱門:全球壽命最長的王朝,傳承2680年共126個皇帝,如今依然昌盛不衰(2023-06-27 02:25:03)
-
GGII:5月國內(nèi)動力電池裝機量約27GWh 同比
GGII依據(jù)終端零售數(shù)據(jù)統(tǒng)計顯示,2023年5月國內(nèi)新能源汽車銷量約為57 9
-
龍之谷pk職業(yè)推薦_龍之谷pk最強
1、《龍之谷》二轉(zhuǎn)游俠[影舞 風行]PK厲害游俠是弓箭手轉(zhuǎn)職的一個職業(yè),
-
中電控股:藍凌志將卸任CEO,蔣東強今年10
新京報貝殼財經(jīng)訊中電控股6月26日午間在港交所公告,蔣東強將接替藍凌
-
背后的溫柔第二部(背后的溫柔)_環(huán)球快播
1、其實我覺得兩個人是分是和也許就在那一念之間世界上形容愛情的文字
-
中央氣象臺:我國近海海域?qū)⒂?-7級風
一、近海海域天氣實況26日02時至14時,黃海中部和南部海域出現(xiàn)了5~7級
-
動態(tài):6月26日常熟鴻嘉氟冰晶石價格平穩(wěn)
6月26日,常熟市鴻嘉氟科技有限公司冰晶石報價平穩(wěn),合成冰晶石價格在7
-
原TES三C重聚?369、Knight、Jackeylove組
直播吧6月26日訊?25日晚間國家體育總局公布了杭州亞運會LOL項目的陣容
-
凱宏投觀:各國央行應(yīng)向新興市場學習決策經(jīng)
【凱宏投觀:各國央行應(yīng)向新興市場學習決策經(jīng)驗】凱投宏觀首席經(jīng)濟學家
-
快看:81歲創(chuàng)始人二闖IPO,大股東卻“臨陣
后疫情時代下,“嗅覺經(jīng)濟”逆勢而行,受到消費者和資本的關(guān)注,行業(yè)之
-
環(huán)球新消息丨V觀財報|電科院創(chuàng)始人胡德霖
中新經(jīng)緯6月26日電電科院26日晚公告披露,公司創(chuàng)始人胡德霖因病去世,
- 世界快看:寶能集團再
- 嘉禾五中:弘揚優(yōu)秀傳
- 美國開查“泰坦”號失
- 73800元起!比亞迪海
- 世界快看:寶能集團再被強制執(zhí)行1.35億 寶能集
- 嘉禾五中:弘揚優(yōu)秀傳統(tǒng)文化 增強學生文化自信
- 美國開查“泰坦”號失事 當務(wù)之急先回收殘骸
- 73800元起!比亞迪海鷗車型新增暖陽白外觀和深
- 焦點快報!馬太效應(yīng)顯現(xiàn),華盛頓州計劃強制要求
- 周杰倫緋聞事件_周杰倫出軌空姐并致其懷孕
- 期貨公司觀點匯總一張圖:6月26日有色系(銅、
- 突發(fā)!甘肅一餐飲店發(fā)生爆炸,有人受傷 焦點訊
- 濟南計劃3年為1000家以上企業(yè)“診斷把脈” 定
- 亞洲杯首戰(zhàn)告捷 中國女籃大勝黎巴嫩
- 滾動
- 綜合
- 房產(chǎn)
- 微信小游戲貪吃蛇無盡大作戰(zhàn)兌換碼2023
- 華夏商務(wù)網(wǎng)官網(wǎng) 華夏商務(wù)專函單號查詢NF32
- 一條全是背影的視頻致敬禁毒英雄 全球聚看
- 環(huán)球要聞:預計年內(nèi)上市 奇瑞TJ-1官方定名
- 人民幣繼續(xù)走低,出口會怎么樣|外貿(mào)妙談
- S7售價超預期,爆款潛力突出 環(huán)球滾動
- 觀天下!剛剛!漳州發(fā)布義務(wù)教育學校招生錄
- 廣東佛山:住房公積金貸款上限擬提至50萬元
- 網(wǎng)貸騷擾工作單位怎么辦?網(wǎng)貸怎么協(xié)商只還
- 771.88公斤!“新冬60號”再次刷新南疆早熟
- CPA交費進入倒計時!交費越晚考場越遠是真的