12.5重写按键驱动——同步互斥阻塞

前言:

思考,我们写的按键驱动,可能会出现多个应用程序打开同一个驱动。

测试确实如此,有三个一样的进程,不同PID:

怎么保证同一时刻只能有一个程序打开呢。我们想可以用如下代码实现:

int canopen =1;

然而,实际--canopen在硬件操作分为三步:

  1. 从寄存器读出

  2. 修改

  3. 写回寄存器

在这三个过程中,随时可能发生被另外一个程序所打断。

那有没有一种机制可以不被打断,有的,有下面几种方法:

1.原子操作

2.信号量

3.阻塞

一.同步互斥阻塞之原子操作

1.定义:

    所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束

原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分。将整个操作视作一个整体是原子性的核心特征。

2.常用原子操作函数举例:

atomic_t v = ATOMIC_INIT(0);     //定义原子变量v并初始化为0

atomic_read(atomic_t *v);        //返回原子变量的值

void atomic_inc(atomic_t *v);    //原子变量增加1

void atomic_dec(atomic_t *v);    //原子变量减少1

int atomic_dec_and_test(atomic_t *v); //自减操作后测试其是否为0,为0则返回true,否则返回false。

3.改代码:

测试:(互斥阻塞)

二.同步互斥阻塞之信号量

1.定义:

信号量(semaphore)是用于保护临界区的一种常用方法,只有得到信号量的进程才能执行临界区代码。

当获取不到信号量时,进程进入休眠等待状态。

定义信号量

struct semaphore sem;

初始化信号量

void sema_init (struct semaphore *sem, int val);

void init_MUTEX(struct semaphore *sem);//初始化为0

static DECLARE_MUTEX(button_lock);     //定义互斥锁

获得信号量

void down(struct semaphore * sem);

int down_interruptible(struct semaphore * sem);

int down_trylock(struct semaphore * sem);

释放信号量

void up(struct semaphore * sem);

更改代码:

测试:

一开始运行运行两次测试程序,ps查看:一个处于睡眠等待按键状态,一个处于僵死状态(在down休眠)

执行kill -9 774后,立马打印secondddrv_butttons_fasync

再次ps,原先那个僵死的进程变成睡眠状态

三.同步互斥阻塞之阻塞

阻塞操作    

是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作。

被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足。

非阻塞操作  

进程在不能进行设备操作时并不挂起,它或者放弃,或者不停地查询,直至可以进行操作为止。

fd = open("...", O_RDWR | O_NONBLOCK); //有O_NONBLOCK为非阻塞,没有默认阻塞

发布了114 篇原创文章 · 获赞 17 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_40535588/article/details/90731185