首页 > 代码库 > linux设备驱动中的并发控制
linux设备驱动中的并发控制
并发控制的概念
----并发指的是多个执行单元并行执行,而并发的执行单元对共享资源(硬件资源和
----软件上的全局变量、静态变量等)的访问则很容易导致竞态。
竞态发生的情况
----对称多处理器(SMP)的多个CPU
----单CPU内进程与抢占它的进程
----中断(硬中断、软中断、Tasklet、底半部)与进程之间
解决竞态问题的途径
----保证对共享资源的互斥访问,所谓互斥访问是指一个执行单元在访问共享资源的时候,
----其他的执行单元被禁止访问。
----访问共享资源的代码称为临界区,临界区需要被以某种互斥机制加以保护。
互斥机制
----中断屏蔽
----原子操作
----自旋锁
----信号量
中断屏蔽
----local_irq_disable() //屏蔽中断
----/*临界区*/
----local_irq_enable() //开中断
----这种方式并不能解决SMP多CPU引发的竞态
原子操作
----实现方法:
----头文件asm/atomic.h
----atomic_t v=ATOMIC_INIT(1); //定义原子变量v并初始化为1
----if(! atomic_dec_and_test(v)) //自减1测试
----{ atomic_inc(&v); return –EBUSY; } //设备忙返回错误码
---- …… //临界区代码
----atomic_inc(&c); //释放设备
自旋锁
----spinlock_t lock; //定义自旋锁
----spin_lock_init(&lock); //初始化自旋锁
----spin_lock(&lock); //获得自旋锁
----…… //临界区代码
----spin_unlock(&lock); //释放自旋锁
----一个例子:
static int cdev_open(struct inode*inode, struct file *file)
{
spin_lock(&lock);
if(flag== 1){
flag--;
spin_unlock(&lock);
printk(KERN_INFO"cdev_open !\n"); //临界区代码
return0;
}else{
spin_unlock(&lock);
return-EBUSY;
}
return0;
}
static int cdev_release(struct inode*inode, struct file *file)
{
flag++;
return 0;
}
----说明:自旋锁是一种忙等待锁,中间不能有可引起睡眠的操作;临界区不能太长;自旋
----锁可用在中断上下文中
信号量
----需要头文件linux/semaphore.h
----struct semaphore sem; //定义信号量
----sema_init(&sem,1); //初始化信号量
----down_interruptible(&sem); //获取信号量
----…… //临界区代码
----up(&sem); //释放信号量
----说明:信号量不同于自旋锁,他是一种睡眠锁,不能用在中断上下文中。
----一种简单的使用方法:
----if(down_trylock(&sem)) //尝试打开锁
----return –EBUSY; //设备忙
----…… //临界区代码
----up(&sem); //释放打开的锁
linux设备驱动中的并发控制