文章目录
-
- 1.1 休眠与唤醒
-
- 1.1.1 适用场景
- 1.1.2 内核函数
-
- 1.1.2.1 休眠函数
- 1.1.2.2 唤醒函数
- 19.1.3 驱动框架
- 1.1.4 编程
-
- 1.1.4.1 驱动程序关键代码
- 1.1.4.2 应用程序
- 1.1.5 上机实验
- 1.1.6 使用环形缓冲区改进驱动程序
- 1.2 POLL机制
-
- 1.2.1 适用场景
- 1.2.2 使用流程
- 1.2.3 驱动编程
- 1.2.4 应用编程
- 1.2.5 现场编程
- 1.2.6 上机实验
- 1.2.7 POLL机制的内核代码详解
- 1.2.7.1 sys_poll函数
-
- 1.2.7.2 do_sys_poll函数
- 1.2.7.3 do_poll函数
- 1.3 异步通知
-
- 1.3.1 适用场景
- 1.3.2 使用流程
- 1.3.3 驱动编程
- 1.3.4 应用编程
- 1.3.5 现场编程
- 1.3.6 上机编程
- 1.3.7 异步通知机制内核代码详解
- 1.4 阻塞与非阻塞
-
- 1.4.1 应用编程
- 1.4.2 驱动编程
- 1.4.3 驱动开发原则
- 1.5 定时器
-
- 1.5.1 内核函数
- 1.5.2 定时器时间单位
- 1.5.3 使用定时器处理按键抖动
- 1.5.4 现场编程、上机
- 1.5.5 深入研究:定时器的内部机制
- 1.5.6 深入研究:找到系统滴答
- 1.6 中断下半部tasklet
-
- 1.6.1 内核函数
-
- 1.6.1.1 定义tasklet
- 1.6.1.2 使能/禁止tasklet
- 1.6.1.3 调度tasklet
- 1.6.1.4 kill tasklet
- 19.6.2 tasklet使用方法
- 19.6.3 tasklet内部机制
- 1.7 工作队列
-
- 1.7.1 内核函数
-
- 1.7.1.1 定义work
- 1.7.1.2 使用work:schedule_work
- 1.7.1.3 其他函数,要么有信 等待处理(本节课程不涉及信 )。
假设g_key等于0,那么APP会执行到上述代码第49行时进入休眠状态。它被谁唤醒控制的中断服务程序:
上述代码中,第72行确定按键值g_key,g_key也就变为TRUE了。
然后在第73行唤醒gpio_key_wait中的第1个线程。
注意这2个函数,一个没有使用“&”,另一个使用了“&”:
1.1.4.2 应用程序
应用程序并不复杂,调用open、read即可,代码在button_test.c中:
在33行~38行的循环中,APP基本上都是休眠状态。你可以执行top命令查看CPU占用率。
1.1.5 上机实验
跟上一节视频类似,需要先修改设备树,请使用上一节视频的设备树文件。
然后安装驱动程序,运行测试程序。
1.1.6 使用环形缓冲区改进驱动程序
使用GIT命令载后,源码位于这个目录下:
使用环形缓冲区,可以在一定程序上避免按键数据丢失,关键代码如下:
使用休眠-唤醒的方式等待某个事件发生时,有一个缺点:等待的时间可能很久。我们可以加上一个超时时间,这时就可以使用poll机制。
① APP不知道驱动程序中是否有数据,可以先调用poll函数查询一下,poll函数可以传入超时时间;
② APP进入内核态,调用到驱动程序的poll函数,如果有数据的话立刻返回;
③ 如果发现没有数据时就休眠一段时间;
④ 当有数据时,比如当按下按键时,驱动程序的中断服务程序被调用,它会记录数据、唤醒APP;
⑤ 当超时时间到了之后,内核也会唤醒APP;
⑥ APP根据poll函数的返回值就可以知道是否有数据,如果有数据就调用read得到数据
1.2.2 使用流程
妈妈进入房间时,会先看小孩醒没醒,闹钟响之后走出房间之前又会再看小孩醒没醒。
注意:看了2次小孩!
POLL机制也是类似的,流程如下:

函数执行流程如上图①~⑧所示,重点从③开始看。假设一开始无按键数据:
③ APP调用poll之后,进入内核态;
④ 导致驱动程序的drv_poll被调用:
注意,drv_poll要把自己这个线程挂入等待队列wq中;假设不放入队列里,那以后发生中断时,中断服务程序去哪里找到你嘛br> drv_poll还会判断一下:有没有数据啊回这个状态。
⑤ 假设当前没有数据,则休眠一会;
⑥ 在休眠过程中,按下了按键,发生了中断:
在中断服务程序里记录了按键值,并且从wq中把线程唤醒了。
⑦ 线程从休眠中被唤醒,继续执行for循环,再次调用drv_poll:
drv_poll返回数据状态
⑧ 哦,你有数据,那从内核态返回到应用态吧
⑨ APP调用read函数读数据
如果一直没有数据,调用流程也是类似的,重点从③开始看,如下:
③ APP调用poll之后,进入内核态;
④ 导致驱动程序的drv_poll被调用:
注意,drv_poll要把自己这个线程挂入等待队列wq中;假设不放入队列里,那以后发生中断时,中断服务程序去哪里找到你嘛br> drv_poll还会判断一下:有没有数据啊回这个状态。
⑤ 假设当前没有数据,则休眠一会;
⑥ 在休眠过程中,一直没有按下了按键,超时时间到:内核把这个线程唤醒;
⑦ 线程从休眠中被唤醒,继续执行for循环,再次调用drv_poll:
drv_poll返回数据状态
⑧ 哦,你还是没有数据,但是超时时间到了,那从内核态返回到应用态吧
⑨ APP不能调用read函数读数据
注意几点:
① drv_poll要把线程挂入队列wq,但是并不是在drv_poll中进入休眠,而是在调用drv_poll之后休眠
② drv_poll要返回数据状态
③ APP调用一次poll,有可能会导致drv_poll被调用2次
④ 线程被唤醒的原因有2:中断发生了去队列wq中把它唤醒,超时时间到了内核把它唤醒
⑤ APP要判断poll返回的原因:有数据,还是超时。有数据时再去调用read函数。
1.2.3 驱动编程
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!