• Linux 设备驱动--- 并发 与 竞态 --- atomic_t --- atomic_dec_and_test --- 原子操作


    并发:

              多个执行单元同时被执行.


    竞态:

              并发的执行单元对资源 ( 硬件资源和软件上的全局变量等 ) 的访问导致的竞争状态.

              


    并发的处理:

              处理并发的常用技术是加锁或者互斥,即保证在任何时间只有一个执行单元可以操作共享资源.

              在 Linux 内核中主要通过 semaphore 机制 (信号量)和spin_lock 机制 (自旋锁)实现.


    原子操作:

    定义:

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

    分为 位 和 整型变量 两类原子操作。


    atomic_t  :

    1. typedef struct {  
    2. volatile int counter;  
    3. } atomic_t;  

    原子操作函数:

    整型原子操作:

    1. void atomic_set(atomic_t *v, int i);   //设置原子变量v的值为i  
    2. atomic_t v = ATOMIC_INIT(0);            //定义原子变量v, 并初始化为0  **************************  
    3. atomic_read(atomic_t *v);              //获得原子变量的值,返回原子变量的值  
    4. void atomic_add(int i, atomic_t *v);    //原子变量+i  
    5. void atomic_sub(int i, atomic_t *v);    //原子变量-i  
    6. void atomic_inc(atomic_t *v);           //原子变量+1            *******************************  
    7. void atomic_dec(atomic_t *v);           //原子变量-1  

    对原子变量执行自增,自减和减操作后 ,测试其是否为0,为 0 则返回 true,否则返回 false :

    1. int atomic_inc_and_test(atomic_t *v);   
    2. int atomic_dec_and_test(atomic_t *v);              ***********************  
    3. int atomic_sub_and_test(int i, atomic_t *v);          


    对原子变量进行加/减,自增/自减操作,并返回新的值:

    1. int atomic_add_return(int i, atomic_t *v);  
    2. int atomic_sub_return(int i, atomic_t *v);  
    3. int atomic_inc_return(atomic_t *v);  
    4. int atomic_sub_return(atomic_t *v);  

    位原子操作:

    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. int test_bit(nr, void *addr);    //返回addr地址的nr位  
    5. int test_and_set_bit(nr, void *addr);  
    6. int test_and_clear_bit(nr, void *addr);  
    7. int test_and_change_bit(nr, void *addr);  
    8. 先设值,后返回。  



    实例 --- 原子操作:

    1,定义一原子变量:

    在程序开头定义原子变量,初始化为 1 :

    1. static atomic_t canopen = ATOMIC_INIT(1);     //定义原子变量并初始化为1  

    2,在 open 函数里检测原子变量值:

    如果减 一 为 0 , !true 为 假 ,if 里面的原子变量加一恢复到  0

    • {  
    •     atomic_inc(&canopen);  
    •     return -EBUSY;  
    • }  

    3,在退出时 close 函数 恢复原子变量值:

    最后, 在应用程序退出时 close 函数, 自增 恢复原子变量值为 1:

    1. atomic_inc(&canopen);  

    4,应用程序测试:

    在应用程序里面打开驱动程序:

    1. fd = open("/dev/buttons", O_RDWR);  
    2. if (fd < 0)  
    3. {  
    4.     printf("can't open! ");  
    5.     return -1;  
    6. }  


    当有两个应用程序打开同一这个驱动的时候,打印 can't open! .

  • 相关阅读:
    mybatis 控制台打印sql脚本
    删除git库中untracked files(未监控)的文件
    亚马逊云实例被攻击 一个月账单三百多美刀
    ubuntu下搜索文件
    django 富文本展示 以及 post提交出错
    亚马逊EC2弹性IP收费
    redis 相关命令
    使用XSHELL连接EC2虚拟机实例
    springMVC下集成active MQ发送邮件
    ubuntu下安装JDK并搭建activeMQ
  • 原文地址:https://www.cnblogs.com/wanghuaijun/p/7705045.html
Copyright © 2020-2023  润新知