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

来源:互联网 发布:以色列粮食进口数据 编辑:程序博客网 时间:2024/06/11 21:08

原子锁:

摘自《linux设备驱动开发详解》第七章

1.设置原子变量的值
           void atomic_set(atomic_t *v, int i); //设置原子变量的值为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);
上述操作对原子变量执行自增、自减和减操作后(注意没有加)测试其是否为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中有着它的定义以及操作函数。

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__(".setmips3\n""1:ll%0, %1# atomic_add\n""addu%0, %2\n""sc%0, %1\n""beqzl%0, 1b\n"".setmips0\n": "=&r" (temp), "=m" (v->counter): "Ir" (i), "m" (v->counter));} else if (cpu_has_llsc) {unsigned long temp;__asm__ __volatile__(".setmips3\n""1:ll%0, %1# atomic_add\n""addu%0, %2\n""sc%0, %1\n""beqz%0, 2f\n"".subsection 2\n""2:b1b\n"".previous\n"".setmips0\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__(".setmips3\n""1:ll%0, %1# atomic_sub\n""subu%0, %2\n""sc%0, %1\n""beqzl%0, 1b\n"".setmips0\n": "=&r" (temp), "=m" (v->counter): "Ir" (i), "m" (v->counter));} else if (cpu_has_llsc) {unsigned long temp;__asm__ __volatile__(".setmips3\n""1:ll%0, %1# atomic_sub\n""subu%0, %2\n""sc%0, %1\n""beqz%0, 2f\n"".subsection 2\n""2:b1b\n"".previous\n"".setmips0\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)
其实就是设置一个整形变量,对这个整形变量进行加减操作。可应用于对引用资源的计数。

        在对这个整形变量进行加减的过程中,是在原子状态下进行的,汇编语言先不管,那几段少的可怜的c代码中,v->count进行加减的时候都是要关中断的。确保当前process占用内核。

       原子锁也可以用于同步。比如下面的程序,至允许在一个进程中打开资源。程序也是摘自《linux设备驱动详解》

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; /*已经打开*/ }...return 0; /* 成功*/}static int xxx_release(struct inode *inode, struct file *filp){atomic_inc(&xxx_available); /* 释放设备*/return 0;}


还有位操作的的原子锁,原理跟上面的差不多,只不过这是用bit操作,这样操作更简洁明了,非0即1,就是缺少了计数这个功能。

1.设置位
          void set_bit(nr, void *addr);
         上述操作设置addr 地址的第nr 位,所谓设置位即将位写为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)操作等同于执行test_bit (nr, void *addr)后
再执行xxx_bit(nr, void *addr)。


原创粉丝点击