一、linux应用编程-2.2-并发与竞争实验

目录

一、原子操作实验

二、自旋锁实验

  三、信号量实验

四、互斥体


一、原子操作实验

        使用原子操作来实现对led这个设备互斥访问,即一次只允许一个应用访问LED。

        主要思想:

        ①、在驱动入口函数处初始化原子变量lock为1;

        ②、每次调用open函数打开设备的时候判断lock的值,如果为负数,则LED正在使用中;

        ③、LED使用完毕,应用程序调用close时候,将lock加1,恢复成初始化值;

        部分代码如下:

static int __init led_init(void)
{
    //初始化原子变量为1
    atomic_set(&lock, 1);
}

static int led_open()
{
    if (!atomic_dec_and_test(&lock))
    {
        //因为atomic_dec_and_test将lock减1了,退出去必须加1恢复原样
        atomic_inc(&lock);
        return -1;
    }
}

static void led_release()
{
    //退出时+1,恢复初始值
    atomic_inc(&lock);
}

二、自旋锁实验

        如果在open函数中申请自旋锁,在release中释放自旋锁,这样虽然可以实现一次只能有一个应用访问LED,但是不可取,因为自旋锁使用有个注意事项就是保护的区域要尽可能短。所以考虑用一个变量来指示设备的使用情况,在open函数里该变量加1,在release函数中改变了减1,只有该变量为0表示LED可以被使用,大于0表示LED在使用中。我们只需要使用自旋锁保护这个变量即可。

        主要思想:

        ①、在驱动入口函数处初始化自旋锁;

        ②、每次调用open函数打开设备的时候判断变量的值,如果大于0,则LED正在使用中;如果为0,则将该变量加1,表示设备正在被使用。

        ③、LED使用完毕,应用程序调用close时候,将该变量减1;

        部分代码如下:

        考虑兼容性,可以将spin_lock、spin_unlock分别用spin_lock_irqsave、spin_unlock_irqrestore代替。

static int __init led_init(void)
{

    //初始化自旋锁
    spin_lock_init(&lock);
}

static int led_open()
{
    //加锁
    spin_lock(&lock);
    if (stats)
    {
        //解锁
        spin_unlock(&lock);
        return -EBUSY;
    }
    stats++;
    //解锁
    spin_unlock(&lock);
}

static void led_release()
{
    //加锁
    spin_lock(&lock);
    if (stats)
        stats--;
    //解锁
    spin_unlock(&lock);
}

  三、信号量实验

        因为信号量可以引起休眠,因此信号量保护的临界区没有时间限制,这样就可以在open中申请信号量,在release中释放信号量,只要不用再中断里就行了。

        部分代码如下:

static int __init led_init(void)
{
    //初始化信号量
    sema_init(&sem);   
}

static int led_open()
{
    //申请信号量
    down(&sem);    
}

static void led_release()
{
    //释放信号量
    up(&sem);
}

        应用程序A获取信号量成功后,sem值减1位为0,应用程序B如果也要使用LED,应为获取不到信号量进入休眠,当A运行完毕后就会释放信号量加1变为1,B就会被唤醒,获取成功开始使用LED。示例结果如下:

四、互斥体

        最适合互斥访问的还得用互斥体。与信号量用法类似,部分代码如下:

static int __init led_init(void)
{
    //初始化互斥体
    mutex_init(&mutex);
}

static int led_open()
{
    //获取互斥体
    //metho1:可以被信号打断
    if (mutex_lock_interruptible(&mutex))
        return -ERESTARTSYS;

    //methor2:不能被信号打断
    mutex_lock(&mutex);
}

static int led_release()
{
    //释放互斥体
    mutex_unlock(&mutex);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值