来源:百问网1.适用场景在前面引入中断时 , 我们曾经举过一个例子:
作者:韦东山
本文字数:2344 , 阅读时长:4分钟
文章插图
妈妈怎么知道卧室里小孩醒了?
- 时不时进房间看一下:查询方式
简单 , 但是累 - 进去房间陪小孩一起睡觉 , 小孩醒了会吵醒她:休眠-唤醒
不累 , 但是妈妈干不了活了 - 妈妈要干很多活 , 但是可以陪小孩睡一会 , 定个闹钟:poll方式
要浪费点时间 , 但是可以继续干活 。妈妈要么是被小孩吵醒 , 要么是被闹钟吵醒 。 - 妈妈在客厅干活 , 小孩醒了他会自己走出房门告诉妈妈:异步通知
妈妈、小孩互不耽误
- App不知道驱动程序中是否有数据 , 可以先调用poll函数查询一下 , poll函数可以传入超时时间;
- APP进入内核态 , 调用到驱动程序的poll函数 , 如果有数据的话立刻返回;
- 如果发现没有数据时就休眠一段时间;
- 当有数据时 , 比如当按下按键时 , 驱动程序的中断服务程序被调用 , 它会记录数据、唤醒APP;
- 当超时时间到了之后 , 内核也会唤醒APP;
- APP根据poll函数的返回值就可以知道是否有数据 , 如果有数据就调用read得到数据
2.使用流程妈妈进入房间时 , 会先看小孩醒没醒 , 闹钟响之后走出房间之前又会再看小孩醒没醒 。
注意:看了2次小孩!
POLL机制也是类似的 , 流程如下:
文章插图
函数执行流程如上图①~⑧所示 , 重点从③开始看 。假设一开始无按键数据:
③ APP调用poll之后 , 进入内核态;
④ 导致驱动程序的drv_poll被调用:
注意 , drv_poll要把自己这个线程挂入等待队列wq中;假设不放入队列里 , 那以后发生中断时 , 中断服务程序去哪里找到你嘛?
drv_poll还会判断一下:有没有数据啊?返回这个状态 。
⑤ 假设当前没有数据 , 则休眠一会;
⑥ 在休眠过程中 , 按下了按键 , 发生了中断:
在中断服务程序里记录了按键值 , 并且从wq中把线程唤醒了 。
⑦ 线程从休眠中被唤醒 , 继续执行for循环 , 再次调用drv_poll:
drv_poll返回数据状态
⑧ 哦 , 你有数据 , 那从内核态返回到应用态吧
⑨ APP调用read函数读数据
如果一直没有数据 , 调用流程也是类似的 , 重点从③开始看 , 如下:
③ APP调用poll之后 , 进入内核态;
④ 导致驱动程序的drv_poll被调用:
注意 , drv_poll要把自己这个线程挂入等待队列wq中;假设不放入队列里 , 那以后发生中断时 , 中断服务程序去哪里找到你嘛?
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函数 。
3. 驱动编程使用poll机制时 , 驱动程序的核心就是提供对应的drv_poll函数 。
推荐阅读
- Linux ALSA 图解
- Linux 下的交互式进程浏览器 htop 3.0.0 发布
- 带你玩转 Linux Shellcode
- 在Linux中查找已连接网络的WiFi密码
- 呕心沥血整理的linux服务器一条龙服务
- Linux select/poll机制原理分析
- Linux安全技巧汇总,防止扫描,禁止空密码,强制用V2等
- 使用growpart工具完成Linux系统盘分区扩容
- Linux下如何知道是否有人在使坏?
- 树莓派无屏上手指南