日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

内核的同步机制(原子锁)

發(fā)布時間:2023/12/20 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 内核的同步机制(原子锁) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原子鎖:

摘自《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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。