1.同步机制:原子性操作——在执行过程中不会被其它代码中断的操作 存在于 asm/atomic.h
static atomic_t canopen = ATOMIC_INIT(1); 将canopen初始化为原子性变量,赋值为1
在OPEN函数中添加如下判断: 当打开驱动时需要判断是否已经被驱动打开
if(!atomic_dec_and_test(&canopen) ) canopen自减1后与0比较并返回结果,判断是否为0
{
atomic_inc(&canopen); 变量加一
return -EBUSY;
在CLOSE函数中添加:
atomic_dec(&canopen); 变量减一
第一次打开驱动时,变量值为1,判断后为假,跳过if继续执行程序;以后再次打开驱动时,判断为真,则跳出程序。
2.互斥机制:信号量——用于保护临界区的一种常见方法,只有得到信号量的进程才能执行临界区代码 存在于linux/semaphore.h
static DECLARE_MUTEX(button_lock); 静态定义和初始化一个互斥锁/信号量
#define __SEMAPHORE_INITIALIZER(name, n)
{
.lock = __SPIN_LOCK_UNLOCKED((name).lock),
.count = n,
.wait_list = LIST_HEAD_INIT((name).wait_list),
}
#define DECLARE_MUTEX(name) struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
在OPEN函数中添加: down(&button_lock); 开启互斥锁/获得信号量,无法获得便会进入休眠
在CLOSE函数中添加: up(&button_lock
); 关闭互斥锁/释放信号量
开启互斥锁后,其他程序无法访问互斥锁之后的代码,会陷入不可中断的睡眠状态;当之前的进程被杀死时,睡眠的进程就会被唤醒。
3.阻塞机制:阻塞—执行设备操作时若不能获得资源则挂起进程。直到满足可操作的条件后再进行操作。
被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足。
非阻塞—进程在不能进行设备操作时并不挂起,会放弃或者不断的查询,直到可以进行操作为止。
应用程序:
fd = open("/dev/open",O_RDWR | O_NONBLOCK); 以非阻塞模式打开
fd = open("/dev/open",O_RDWR | O_BLOCK); 以阻塞模式打开
OPEN函数中:
if(file->f_flags & O_NONBLOCK) 若为非阻塞模式,则尝试开启互斥,即无法开启不会休眠
{
if(down_trylock(&button_lock))
return -EBUSY;
}
else 若为阻塞模式,则开启互斥,即无法开启则会休眠
{
down(&button_lock);
}
READ函数中:
if(file->f_flags & O_NONBLOCK) 若为非阻塞模式,则判断是否有按键按下
{
if(!ev_press)
return -EAGAIN;
}
else 若为阻塞模式,则等待按键发生
{
wait_event_interruptible(button_waitq,ev_press);
}