linux中原子量的學習和理解


原子量的理解

我們知道晶體管有兩種狀態,通電和不通電,對應着二進制存儲中的1和0,這和開關的原理是一樣的,不過開關可以由人來控制,而晶體管的狀態是由電來控制的;我們可以利用一種特殊的門電路組合控制一個晶體管中的狀態不再受所通入電流的影響,可以說是把一位數存到了這個晶體管里面;當需要讀取時,開放晶體管的后端就可以讓其中存儲的狀態流出來;當需要改寫時,通過一種特殊的門電路組合又可以控制這個晶體管受流通電流的影響,這時就可以改變存儲在其中的值。

在匯編中要改寫一個數據通常需要三步,從內存中取出數據到寄存器,在寄存器中修改,再將數據存回內存,即ldr r0,0x10000040  mov r1,#4  str r1,[r0]   也就是說修改一個地址處存的數值不是一步完成的,而在c語言中這是一步完成的:*p=4(假設*p=0x10000040)。

我們知道指針的本質就是對應存儲的數據被解釋為一個地址,而對於類似變量這種對應存儲的數據被解釋為一個對應類型的數值,存儲的都是一個數,只是在不同環境下被解釋出來的含義不一樣而已。由上面解釋的晶體管的物理狀態可知,一個晶體管同一時間只能存儲一種狀態,組合起來就是一個內存塊同一時間只能存儲一個固定不變的值,也就是說一個指針同一時間只能指向一個固定的地址;然而一個內存塊的地址卻可以存儲在多個指針對應的內存塊中,也就是說可以同時有多個指針指向同一塊內存,總結起來就是時間上唯一,空間上不唯一。

由於有這種屬性,當有多個指針指向同一塊內存,並通過其中某一個指針對指向的數據進行修改后,再通過其他指針取得的這個內存塊的數據是那個已經被改變后的值。因為修改一個地址的值需要至少需要三步,而內核又是搶占式的,現在我們假設有兩個指針A,B同時指向了同一塊內存m,當我們執行線程1用指針A取出這個內存的數據准備運算時,發生了進程調度,跳到線程2執行,此時指針B也取出了這個數據准備運算時也發生了進程調度返回到線程1執行,指針A修改值后又存回這個內存,如果在進程1用的這個內存數據之前線程2執行將數據修改后存入這個內存地址,那么線程1取得的數值將不再是它本身保存的那個而且它以為它是沒錯的,就會發生數據錯誤。

針對以上假設的這種情況,經常把全局變量設置為原子量,在指令上使得對這個全局變量的取出、賦值、存回是不可被打斷的,這就對應着c語言中的一條語句。

在Linux kernel里面原子量定義如下:

typedef struct {volatile int counter; } atomic_t;


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: