字符设备驱动的同步互斥阻塞

目的在同一时刻,只能有一个app打开驱动文件,有三种方法

1原子操作

原子操作指的是在执行过程中不会被别的代码路径所中断的操作。
常用原子操作函数举例:
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。

1.先定义一个原子变量
字符设备驱动的同步互斥阻塞
2.这时候有有应用要打开驱动,先看看原子值自减是否为0
字符设备驱动的同步互斥阻塞
3.关闭的时候自动加一
字符设备驱动的同步互斥阻塞

信号量

信号量(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);

1.先定义一个信号量
字符设备驱动的同步互斥阻塞
2 获取信号量
字符设备驱动的同步互斥阻塞
3.用完释放
字符设备驱动的同步互斥阻塞

阻塞

阻塞操作
是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作。
被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足。
非阻塞操作
进程在不能进行设备操作时并不挂起,它或者放弃,或者不停地查询,直至可以进行操作为止。

分辨阻塞和非阻塞fd = open("…", O_RDWR | O_NONBLOCK);

如想读一个按键值,若当前没有按键按下,就一直等待有按下才返回,这是“阻塞操作”;
“非阻塞操作”是指若想读一个按键值,若没有按键值可读,则立刻返回一个错误。
分辨他们,是在 open 设备时,加入一个参数。若传入“ O_NONBLOCK”就是非阻塞操作若不传入“ O_NONBLOCK”标记时,
默认为“阻塞操作”。对于“阻塞、非阻塞”,驱动程序要对这个“ O_NONBLOCK”进行理。

对于文件这个结构体有个flags参数来设置阻塞和非阻塞
字符设备驱动的同步互斥阻塞
设置为非阻塞
字符设备驱动的同步互斥阻塞
如果它无法获取这个“信号量”,这个“down(&button_lock);”会陷入休眠。如果“open”打
不开,立刻返回一个错误,
就用了“down_trylock(&button_lock)”这个函数。表示如果无法获取到“信号量”就返回“return
-EBUSY”.