原子操作,顧名思義,就是說像原子一樣不可再細分不可被中途打斷。乙個操作是原子操作,意思就是說這個操作是以原子的方式被執行,要一口氣執行完,執行過程不能夠被os的其他行為打斷,是乙個整體的過程,在其執行過程中,os的其它行為是插不進來的。
在linux中提供了兩種形式的原子操作:
一種是對整數進行的操作
一種是對單獨的位進行操作
在linux中有乙個專門的atomic_t型別(乙個24位原子訪問計數器)和一些對atomic型別變數進行相應操作的的函式
其atomic_t原型如下:
typedef struct atomic_t;
它是乙個只含有乙個volatile型別的成員變數的結構體;因此編譯器不對相應的值進行訪問優化(因為是volatile型別的)。
原子整數操作的使用:
常見的用途是計數器,因為計數器是乙個很簡單的操作,所以無需複雜的鎖機制;
能使用原子操作的地方,盡量不使用複雜的鎖機制;
對atomic_t型別的變數的使用方法以及對其所能進行的操作:
下面是相應的函式及其原型:
******
在其函式的實現體中,有乙個lock_prefix巨集定義,如果選了config_smp,就會定義這麼乙個巨集,與smp相關的一些設定,否則lock_prefix的定義就為空;
******
//原子的讀取atomic_t變數的值,v是這個變數的位址
#define atomic_read(v) ((v)->counter)
//原子的設定atomic_t變數的值,v是這個變數的位址,i要設定的新值;
#define atomic_set(v,i) (((v)->counter) = (i))
//原子的增加atomic_t變數的值,i是要增加的數值,v是這個變數的位址
static __inline__ void atomic_add(int i, atomic_t *v)
//原子的減少atomic_t變數的值,i是要減少的數值,v是這個變數的位址;
static __inline__ void atomic_sub(int i, atomic_t *v)
//原子的對atomic_t變數的值進行減少i的操作,並且檢測其結果是否為0;若為0,返回true,否則,返回false;
//i是要減少的數值,v是這個變數的位址;
static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
//原子的對atomic_t變數的值進行加1的操作,v是這個變數的位址;
static __inline__ void atomic_inc(atomic_t *v)
//原子的對atomic_t變數的值進行減1的操作,v是這個變數的位址;
static __inline__ void atomic_dec(atomic_t *v)
//原子的對atomic_t變數的值進行減少1的操作,並且檢測其結果是否為0;若為0,返回true,否則,返回false;
//v是這個變數的位址;
static __inline__ int atomic_dec_and_test(atomic_t *v)
//原子的對atomic_t變數的值進行加1的操作,並且檢測其結果是否為0;若為0,返回true,否則,返回false;
//v是這個變數的位址;
static __inline__ int atomic_inc_and_test(atomic_t *v)
//原子的對atomic_t變數的值進行加i的操作,並且檢測其結果是否為負;若為負,返回true,否則,返回false;
//i是要增加的數值,v是這個變數的位址;
static __inline__ int atomic_add_negative(int i, atomic_t *v)
//原子的對atomic_t變數的值進行加i的操作,並且將所得結果返回;
//i是要增加的數值,v是這個變數的位址;
static __inline__ int atomic_add_return(int i, atomic_t *v)
//原子的對atomic_t變數的值進行減i的操作,並且將所得結果返回;
//i是要減少的數值,v是這個變數的位址;
static __inline__ int atomic_sub_return(int i, atomic_t *v)
//原子的比較old與v是否相等,若相等,則把new的值寫入到v中,並且返回old的值;
#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
//原子的比較
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/*** atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
** atomically adds @a to @v, so long as it was not @u.
* returns non-zero if @v was not @u, and zero otherwise.
*///原子的對atomic_t變數的值進行加a的操作,直到v等於u,如果v與u不等,返回非零值;否則返回0;
//a是要增加的數值,v是這個變數的位址,u是要比較的值;
#define atomic_add_unless(v, a, u) \
( \
c != (u); \
})#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
#define atomic_inc_return(v) (atomic_add_return(1,v))
#define atomic_dec_return(v) (atomic_sub_return(1,v))
//掩碼
/* these are x86-specific, used by some header files */
#define atomic_clear_mask(mask, addr) \
__asm__ __volatile__(lock_prefix "andl %0,%1" \
: : "r" (~(mask)),"m" (*addr) : "memory")
#define atomic_set_mask(mask, addr) \
__asm__ __volatile__(lock_prefix "orl %0,%1" \
: : "r" (mask),"m" (*(addr)) : "memory")
下面舉例說明原子操作的用法:
定義乙個atomic_c型別的資料很簡單,還可以定義時給它設定初值:
(1) atomic_t u; /*定義 u*/
(2) atomic_t v = atomic_init(0) /*定義 v 並把它初始化為0*/
對其操作:
(1) atomic_set(&v,4) /* v = 4 ( 原子地)*/
(2) atomic_add(2,&v) /* v = v + 2 = 6 (原子地) */
(3) atomic_inc(&v) /* v = v + 1 =7(原子地)*/
如果需要將atomic_t轉換成int型,可以使用atomic_read()來完成:
printk(「%d\n」,atomic_read(&v)); /* 會列印7*/
原子整數操作最常見的用途就是實現計數器。使用複雜的鎖機制來保護乙個單純的計數器是很笨拙的,所以,開發者最好使用atomic_inc()和atomic_dec()這兩個相對來說輕便一點的操作。
還可以用原子整數操作原子地執行乙個操作並檢查結果。乙個常見的例子是原子的減操作和檢查。
int atomic_dec_and_test(atomic_t *v)
這個函式讓給定的原子變數減1,如果結果為0,就返回1;否則返回0
原子位操作
操作函式的引數是乙個指標和乙個位號
第0位是給定位址的最低有效位
原子位操作中沒有特殊的資料型別
例如:set_bit(0, &word);
如:標誌暫存器eflsgs的系統標誌,用於控制i/o訪問,可遮蔽硬體中斷。共32位,不同的位代表不同的資訊,對其中資訊改變都是通過位操作實現的
原子操作中的位操作部分函式如下:
void set_bit(int nr, void *addr) 原子設定addr所指的第nr位
void clear_bit(int nr, void *addr) 原子的清空所指物件的第nr位
void change_bit(nr, void *addr) 原子的翻轉addr所指的第nr位
int test_bit(nr, void *addr) 原子的返回addr位所指物件nr位
int test_and_set_bit(nr, void *addr) 原子設定addr所指物件的第nr位,並返回原先的值
int test_and_clear_bit(nr, void *addr) 原子清空addr所指物件的第nr位,並返回原先的值
int test_and_change_bit(nr, void *addr) 原子翻轉addr所指物件的第nr位,並返回原先的值
原子操作詳解
原子操作 原子操作是指不會被執行緒排程機制打斷的操作 這種操作一旦開始,就一直執行到結束,中間不會被其他程序打斷。它是其他核心同步方法的基石。編寫 時能使用原子操作的,就盡量不要用加鎖機制,因為原子操作給系統帶來的開銷小。一 原子整數操作 1 型別的定義 針對整數的原子操作只能對atomic t型別...
Linux 原子操作
所謂原子操作,就是該操作絕不會在執行完畢前被任何其他任務或事件打斷,也就說,它的最小的執行單位,不可能有比它更小的執行單位,因此這裡 的原子實際是使用了物理學裡的物質微粒的概念。原子操作需要硬體的支援,因此是架構相關的,其api和原子型別的定義都定義在核心原始碼樹的include asm atomi...
linux原子操作
原子操作指的是在執行過程中不會被別的 路徑所中斷的操作,下面列出原子操作相關的函式 1.void atomic set atomic t v,int i 設定原子變數的值為i 2.atomic t v atomic init 0 定義原子變數v並初始化為0 3.atomic read atomic ...