一、异步通知
1、目的:为了使驱动控制通知应用程序执行操作,同进程之间发信号signal
2、方法: 应用程序: fcntl(fd , F_SETOWN , pid) 指定一个进程作为文件的“属主(filp->owner)”,这样内核才知道信号要发给哪个进程
oflags = fcntl(fd , F_GETFL)
fcntl(fd, F_SETFL, Oflags | FASYNC);在设备文件中添加FASYNC标志,驱动中就会调用将要实现的test_fasync函数
驱动程序: test_fasync 函数调用fasync_helper(fd , filp , on , &button_async)初始化button_async结构
在设备资源可获得后,调用kill_fasync()函数激发相应的信号》》应用程序中的signal将会被激发
二、同步
1、目的: 同一时刻只能有一个应用程序打开设备,即驱动程序
2、方法一分析:
if (--canopen != 0)
{
canopen++;
return -EBUSY;
}
正常执行
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">//</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">用一个变量canopen = 1,当一个进程执行驱动open函数时,if(--canopen != 0)为假,则正常执行,当另一个进程也驱动open函数时,此时canopen为0</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">,则不能继续往下执行</span>
但是--canopen并不是原子操作,执行这条语句会有很多步骤,也就会被另一个程序打断,从而要求使用原子操作
3、方法二分析: atomic_t v = ATOMIC_INT(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
if (!atomic_dec_and_test(&canopen))
{
atomic_inc(&canopen);
return -EBUSY;
}
三、互斥
1、信号量是用于保护临界区的一种常用方法,只有得到信号量的进程才能执行临界区代码。当获取不到时进入休眠等待状态。
2、用一个宏定义互斥锁:static DECLARE_MUTEX(button_lock);
3、获取信号量:down(&button_lock)获取信号量 ;//第二次执行到这会休眠
4、释放信号量:up(&button_lock)
四、阻塞
1、阻塞操作是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作。
被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足。
2、非阻塞操作是指进程在不能进行设备操作时并不挂起,它或者被放弃,或者被不停的查询,直至可以进行操作为止。
3、fd = open("...." , O_RDWR | O_NONBLOCK) 表示为非阻塞操作,默认情况为阻塞
4、驱动open函数使用阻塞与非阻塞
5、驱动read函数使用阻塞与非阻塞
谢谢韦老师的视频讲解