我是靠谱客的博主 无奈八宝粥,最近开发中收集的这篇文章主要介绍linux系统下的原子操作,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

   原子操作是指在执行的过程中不会被别的代码路径所中断的操作。

1.整型原子操作

  1.1 设置源自变量的值

      void atomic_set(atomic_t *v,int i);  //设置原子变量的的值为i

      atomic_t v = ATOMIC_INIT(0);         //定义原子变量,并将其初始化为0

  1.2 获取元原子变量的值

      atomic_read(atomic_t *v);            //返回原子变量的值

      这是一个宏定义:#define  atomic_read(v)   (*(volatile int)&(v)->counter)

  1.3 原子变量加减

      void atomic_add(int i,atomic_t *v);   //原子变量增加i

      void atomic_sub(int i,atomic_t *v);   //原子变量减少i

  1.4 原子变量自增、自减

      void atomic_inc(atomic_t *v);

      void atomic_dec(atomic_t *v);

  1.5 操作并测试

      int atomic_int_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。

  1.6 操作并返回

      int atomic_add_and_return(int i,atomic_t *v);

      int atomic_sub_and_return(int i,atomic_t *v);

      int atomic_dec_and_return(atomic_t *v);

      int atomic_inc_and_return(atomic_t *v);

      以上操作后返回新的值。

2. 位原子操作 

   2.1 设置位

      void  set_bit(nr,void *addr);   //设置addr地址的第nr位为1

   2.2 清除位

     void  clear_bit(nr, void *addr); //设置addr地址的第nr位为0

   2.3 改变位

     void change_bit(nr, void *addr); //反置addr的第nr位

   2.4 测试位

     void test_bit(nr,void *addr);    //返回addr的nr位

   2.5 测试并操作位

     void  test_and_set_bit(nr, void *addr);

     void  test_and_clear_bit(nr,void *addr);

     void  test_and_change_bit(nr,void *addr);

3. 自旋锁

   3.1 定义自旋锁

       spinlock_t lock;

   3.2 初始化自旋锁

       spin_lock_init(&lock);

   3.3 获得自旋锁

       spin_lock(&lock);

       spin_trylock(&lock);

   3.4 释放自旋锁

       spin_unlock(&lock);

   还有一些自旋锁的扩展:

     spin_lock_irq() = spin_lock() + local_irq_disable()

     spin_unlock_irq() = sqin_unlock() + lock_irq_enable()

     ...

4. 信号量的使用

       信号量的使用方法和原子变量基本相同,不同的是当获取不到自旋锁时,进程不会原地打转     而是进入睡眠状态,他不会消耗cpu资源。

  4.1 定义信号量

    struct semaphore sem;

  4.2 初始化信号量

    void  sema_init(&sem,int val);

    #define init_MUTEX(sem ,1);

    #define init_LOCKED(sem) sema_init(sem,0)

    还有初始化信号量的简便方式:

    DECLARE_MUTEX(name)

    DECLARE_MUTEX_LOCKED(name)

  4.3 获得信号量

    void down(&sem);              //他会导致睡眠,不能用于中断上下文,且不能被信号打断

    int down_interruptable(&sem);  //睡眠可以被信号打断

    int down_trylock(&sem);     //获得锁返回0,否则返回非0,可用于中断上下文

   

    eg:

    if (down_interruptable(&sem))

         return -ERESTARTSYS;

   4.4 释放信号量

     void up(&sem);

5. 完成量

       完成量是一种比用信号量更好的同步机制,它用于一个执行单元等待另一个执行单元执行完     某事。

  5.1 定义完成量

     struct completion cmp;

  5.2 初始化完成量

    init_completion(&cmp);

    DECLARE_COMPLETION(cmp);

  5.3 等待完成量

    void wait_for_completion(&cmp);

  5.4 唤醒完成量 

    void completion(&cmp);

    void completion_all(&cmp);

6. 自旋锁和信号量的选用原则

   1. 当需要持有锁时间较长时使用信号量较好,较短时使用自旋锁更佳。

   2. 若临界区中包含可能引起阻塞的代码,最好用信号量。

   3. 在被保护的资源需要在中断或软中断中使用的时候只能用自旋锁,或者sem_trylock();

7. 读写信号量

   读写信号量是在信号量基础上的优化,它允许多读一写.

   相关函数:

   struct rw_semaphore sem;

   void init_rwsem(&sem);

   down_read(&sem);

   down_read_trylock(&sem);

   up_read(&sem);

   void down_write(&sem);

   int down_write_trylock(&sem);

   up_write(&sem);

8. 互斥体

   srtuct mutex m;

   mutex_init(&m);

   mutex_lock(&m);

   mutex_lock_interruptable(&m);

   mutex_trylock(&m);

   mutex_unlock(&m);

 

 

 

 

 

 

 

 

 

 

 

 

 

4.3 

   

 

 

转载于:https://blog.51cto.com/lijiajia/1106960

最后

以上就是无奈八宝粥为你收集整理的linux系统下的原子操作的全部内容,希望文章能够帮你解决linux系统下的原子操作所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部