内核的同步机制(原子锁)
原子鎖:
摘自《linux設(shè)備驅(qū)動開發(fā)詳解》第七章
1.設(shè)置原子變量的值
? ? ? ? ? ?void atomic_set(atomic_t *v, int i); //設(shè)置原子變量的值為i
? ? ? ? ? ?atomic_t v = ATOMIC_INIT(0); //定義原子變量v并初始化為0
2.獲取原子變量的值
? ? ? ? ? ? atomic_read(atomic_t *v); //返回原子變量的值
3.原子變量加/減
? ? ? ? ? ?void atomic_add(int i, atomic_t *v); //原子變量增加i
? ? ? ? ? ?void atomic_sub(int i, atomic_t *v); //原子變量減少i
4.原子變量自增/自減
? ? ? ? ? void atomic_inc(atomic_t *v); //原子變量增加1
? ? ? ? ? void atomic_dec(atomic_t *v); //原子變量減少1
5.操作并測試
? ? ? ? ? ? int atomic_inc_and_test(atomic_t *v);
? ? ? ? ? ? int atomic_dec_and_test(atomic_t *v);
? ? ? ? ? ? int atomic_sub_and_test(int i, atomic_t *v);
上述操作對原子變量執(zhí)行自增、自減和減操作后(注意沒有加)測試其是否為0,
為0 則返回true,否則返回false。
6.操作并返回
? ? ? ? ? ?int atomic_add_return(int i, atomic_t *v);
? ? ? ? ? ?int atomic_sub_return(int i, atomic_t *v);
? ? ? ? ? ?int atomic_inc_return(atomic_t *v);
? ? ? ? ? ?int atomic_dec_return(atomic_t *v);
上述操作對原子變量進行加/減和自增/自減操作,并返回新的值。
? ? ? ?atomic。在atomic.h中有著它的定義以及操作函數(shù)。
typedef struct { volatile int counter; } atomic_t;#define ATOMIC_INIT(i) { (i) }/** atomic_read - read atomic variable* @v: pointer of type atomic_t** Atomically reads the value of @v.*/ #define atomic_read(v) ((v)->counter)/** atomic_set - set atomic variable* @v: pointer of type atomic_t* @i: required value** Atomically sets the value of @v to @i.*/ #define atomic_set(v,i) ((v)->counter = (i))/** atomic_add - add integer to atomic variable* @i: integer value to add* @v: pointer of type atomic_t** Atomically adds @i to @v.*/ static __inline__ void atomic_add(int i, atomic_t * v) {if (cpu_has_llsc && R10000_LLSC_WAR) {unsigned long temp;__asm__ __volatile__(" .set mips3 \n""1: ll %0, %1 # atomic_add \n"" addu %0, %2 \n"" sc %0, %1 \n"" beqzl %0, 1b \n"" .set mips0 \n": "=&r" (temp), "=m" (v->counter): "Ir" (i), "m" (v->counter));} else if (cpu_has_llsc) {unsigned long temp;__asm__ __volatile__(" .set mips3 \n""1: ll %0, %1 # atomic_add \n"" addu %0, %2 \n"" sc %0, %1 \n"" beqz %0, 2f \n"" .subsection 2 \n""2: b 1b \n"" .previous \n"" .set mips0 \n": "=&r" (temp), "=m" (v->counter): "Ir" (i), "m" (v->counter));} else {unsigned long flags;raw_local_irq_save(flags);v->counter += i;raw_local_irq_restore(flags);} }/** atomic_sub - subtract the atomic variable* @i: integer value to subtract* @v: pointer of type atomic_t** Atomically subtracts @i from @v.*/ static __inline__ void atomic_sub(int i, atomic_t * v) {if (cpu_has_llsc && R10000_LLSC_WAR) {unsigned long temp;__asm__ __volatile__(" .set mips3 \n""1: ll %0, %1 # atomic_sub \n"" subu %0, %2 \n"" sc %0, %1 \n"" beqzl %0, 1b \n"" .set mips0 \n": "=&r" (temp), "=m" (v->counter): "Ir" (i), "m" (v->counter));} else if (cpu_has_llsc) {unsigned long temp;__asm__ __volatile__(" .set mips3 \n""1: ll %0, %1 # atomic_sub \n"" subu %0, %2 \n"" sc %0, %1 \n"" beqz %0, 2f \n"" .subsection 2 \n""2: b 1b \n"" .previous \n"" .set mips0 \n": "=&r" (temp), "=m" (v->counter): "Ir" (i), "m" (v->counter));} else {unsigned long flags;raw_local_irq_save(flags);v->counter -= i;raw_local_irq_restore(flags);} } /** atomic_sub_and_test - subtract value from variable and test result* @i: integer value to subtract* @v: pointer of type atomic_t** Atomically subtracts @i from @v and returns* true if the result is zero, or false for all* other cases.*/ #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)/** atomic_inc_and_test - increment and test* @v: pointer of type atomic_t** Atomically increments @v by 1* and returns true if the result is zero, or false for all* other cases.*/ #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)/** atomic_dec_and_test - decrement by 1 and test* @v: pointer of type atomic_t** Atomically decrements @v by 1 and* returns true if the result is 0, or false for all other* cases.*/ #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) 其實就是設(shè)置一個整形變量,對這個整形變量進行加減操作。可應(yīng)用于對引用資源的計數(shù)。? ? ? ? 在對這個整形變量進行加減的過程中,是在原子狀態(tài)下進行的,匯編語言先不管,那幾段少的可憐的c代碼中,v->count進行加減的時候都是要關(guān)中斷的。確保當(dāng)前process占用內(nèi)核。
? ? ? ?原子鎖也可以用于同步。比如下面的程序,至允許在一個進程中打開資源。程序也是摘自《linux設(shè)備驅(qū)動詳解》
static atomic_t xxx_available = ATOMIC_INIT(1); /*定義原子變量*/static int xxx_open(struct inode *inode, struct file *filp) {...if (!atomic_dec_and_test(&xxx_available)) //如果xxx_available=0,返回1{atomic_inc(&xxx_available);return - EBUSY; /*已經(jīng)打開*/}...return 0; /* 成功*/ }static int xxx_release(struct inode *inode, struct file *filp) {atomic_inc(&xxx_available); /* 釋放設(shè)備*/return 0; }
還有位操作的的原子鎖,原理跟上面的差不多,只不過這是用bit操作,這樣操作更簡潔明了,非0即1,就是缺少了計數(shù)這個功能。
1.設(shè)置位
? ? ? ? ? void set_bit(nr, void *addr);
? ? ? ? ?上述操作設(shè)置addr 地址的第nr 位,所謂設(shè)置位即將位寫為1。
2.清除位
? ? ? ? ?void clear_bit(nr, void *addr);
? ? ? ?上述操作清除addr 地址的第nr 位,所謂清除位即將位寫為0。
3.改變位
? ? ? ? ?void change_bit(nr, void *addr);
? ? ? ? 上述操作對addr 地址的第nr 位進行反置。
4.測試位
? ? ? ? ?test_bit(nr, void *addr);
? ? ? ? 上述操作返回addr 地址的第nr 位。
5.測試并操作位
? ? ? ? ?int test_and_set_bit(nr, void *addr);
? ? ? ? ?int test_and_clear_bit(nr, void *addr);
? ? ? ? ?int test_and_change_bit(nr, void *addr);
上述test_and_xxx_bit(nr, void *addr)操作等同于執(zhí)行test_bit (nr, void *addr)后
再執(zhí)行xxx_bit(nr, void *addr)。
總結(jié)
以上是生活随笔為你收集整理的内核的同步机制(原子锁)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习 刀光剑影 之屠龙刀
- 下一篇: iphone11信号强度测试软件,信号差