Linux并发与竞争的处理1-------原子操作

产生的原因:Linux是一个多任务操作系统,肯定会存在多个任务共同操作同一段内存或者设备的情况,对于多个任务甚至中断都能访问的资源(共享资源)需要保护。也就是要处理对共享资源的并发访问

同时访问某个数据:同时就是并发 他们之间存在着竞争关系

并发的原因:多任务系统,中断,抢占,多核,线程 等竞争资源他们之间存在竞争关系

如何处理:即在他们可以共同访问的数据段中保证一次只要一个线程访问 即原子访问(这么称呼是因为原子是一个整体 不拆分)

保护的是:数据 是多个线程都会访问的共享数据(可以是全局变量)

——————————————————————————————

本案例使用原子操作 ---一次只允许一个应用程序可以使用 LED 灯。

使用的对象:变量或者位--------linux系统提供了一系列的API函数

——————————————————

/*gpioled设备结构体*/
/*该设备需要的*/
struct gpioled_dev
{
    dev_t devid; /*设备号 32位*/
    int major ;/*主设备号 高12位*/
    int minor ;/*次设备号 低20位*/
    /*cdev表示字符设备 结构体初始化就是初始化结构体变量*/
    struct cdev cdev ;//包含了操作函数集 和 设备号 包含头文件 #include <linux/cdev.h>
    struct class *class; /*类*/
    struct device *device; /*设备*/
    struct device_node *nd; //节点
    int led_gpio ;//
led 所使用的 GPIO 编号
    atomic_t lock;//添加原子 变量  (第一步:使用原子变量代替整形变量)
};
struct gpioled_dev gpioled;

————————————————————————————————————————

/*入口 -注册字符设备*/中注册设备号 /cdev 具体的字符设备操作集合 向内核添加字符设备 自动创建设备节点 不变

在驱动入口函数中:

1、 /*定义原子变量的时候对其初始化*/
    atomic_set(&gpioled.lock, 1);

———————————————————————————

在操作函数集中

static struct file_operations gpioled_fops =
{
    .owner = THIS_MODULE ,
    .open = gpioled_open,
    .write = gpioled_write,
    .release = gpioled_release,
 
};

————————————

法1

static int gpioled_open(struct inode *inode, struct file *filp){
    //私有数据
    filp->private_data = &gpioled ;

 /*第一次打开应用程序的时候需要进行判断 原子变量lock*/

        //atomic_read读取原子变量的值 并且返回
    if( atomic_read(&gpioled.lock) <= 0 ) {  /*说明应用程序已经使用过一次   程序不可运行*/
        return -EBUSY;
    }else{ /*说明可以用 但是需要减去1 因为驱动刚加载的时候为原子变量初始化为1*/
        atomic_dec(&gpioled.lock);      //原子变量自减的API函数 =0

//达到了应用程序只是执行一次的目的
    }

    return 0;
}

法2

static int gpioled_open(struct inode *inode, struct file *filp)
{
    //私有数据
    filp->private_data = &gpioled ;
    /*第一次打开的时候需要进行判断 原子变量lock*/
    //使用一个函数 从 v 减 1,如果结果为 0 就返回真,否则返回假

//atomic_dec_and_test 减 1,如果结果为 0 就返回真,否则返回假
    if( !atomic_dec_and_test(&gpioled.lock) ){ 

        //第一次执行的时候    一开始是1 减去1 为0 返回真 取反 不执行

        //此时如果再次执行 0-1=-1 执行
        //不为0 代表无效 无效之后需要处理 加1 ==由-1变成0、

        atomic_inc(&gpioled.lock);//自增
         return -EBUSY;
    }

    return 0;
}

——————————————————————

static int gpioled_release(struct inode *inode, struct file *filp)
{
    //可以通过私有数据访问struct gpioled_dev gpioled
    struct gpioled_dev *dev = (struct gpioled_dev*)filp->private_data;

    /*释放的时候需要给automic变量加回去*/
    atomic_inc(&dev->lock);//1

    return 0;
}

——————其余API函数不变

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值