今天《升级版全系列嵌入式视频_入门篇》新增一节视频:19.2_POLL机制
时长24分钟,免费观看
何为POLL机制?

给驱动程序加一个闹钟,让APP不必死等数据;

既可以快速掌握 POLL机制,更有对内核代码的详细讲解

多种观看方式:

一, B站(关注UP主-韦东山,视频更新后会有通知)

19.2_POLL机制 :

https://www.bilibili.com/video/BV1w4411B7a4?p=81

(复制到浏览器打开)

二, 官网(http://www.100ask.net)(支持在线观看,爽歪歪)

19.2_POLL机制:

https://wx48b57d2def17d3a6.h5.xiaoe-tech.com/v1/course/video/v_5eb4f73049801_b9Nd6nO7?type=2&pro_id=p_5e63555a13e8b_mmxPu3Zw&entry=1&entry_type=v_5eb4f73049801_b9Nd6nO7&is_redirect=1

(复制到浏览器打开,或者从http://www.100ask.net进入)

温馨提示:

为方便及时通知您,您需要支付1分钱订阅该专栏,

然后依次填写年龄,职位等信息。辛苦了。没有您的允许我们不会泄露这些信息。

三 ,

百度网盘(适合不方便上网的同学)

链接:https://eyun.baidu.com/s/3dFZmEgp

密码:6FJk

路径:

->04_快速入门(正式开始)

->02_嵌入式linux驱动开发基础知识

->19.驱动程序基石

下面是视频文稿:

19.2 POLL机制

19.2.1 适用场景

在前面引入中断时,我们曾经举过一个例子:

妈妈怎么知道卧室里小孩醒了?

① 时不时进房间看一下:查询方式

简单,但是累

② 进去房间陪小孩一起睡觉,小孩醒了会吵醒她:休眠-唤醒

不累,但是妈妈干不了活了

③ 妈妈要干很多活,但是可以陪小孩睡一会,定个闹钟:poll方式

要浪费点时间,但是可以继续干活。

妈妈要么是被小孩吵醒,要么是被闹钟吵醒。

④ 妈妈在客厅干活,小孩醒了他会自己走出房门告诉妈妈:异步通知

妈妈、小孩互不耽误

使用休眠-唤醒的方式等待某个事件发生时,有一个缺点:等待的时间可能很久。我们可以加上一个超时时间,这时就可以使用poll机制。

① APP不知道驱动程序中是否有数据,可以先调用poll函数查询一下,poll函数可以传入超时时间;

② APP进入内核态,调用到驱动程序的poll函数,如果有数据的话立刻返回;

③ 如果发现没有数据时就休眠一段时间;

④ 当有数据时,比如当按下按键时,驱动程序的中断服务程序被调用,它会记录数据、唤醒APP;

⑤ 当超时时间到了之后,内核也会唤醒APP;

⑥ APP根据poll函数的返回值就可以知道是否有数据,如果有数据就调用read得到数据

19.2.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函数。

19.2.3 驱动编程

使用poll机制时,驱动程序的核心就是提供对应的drv_poll函数。

在drv_poll函数中要做2件事:

① 把当前线程挂入队列wq:poll_wait

APP调用一次poll,可能导致drv_poll被调用2次,但是我们并不需要把当前线程挂入队列2次。

可以使用内核的函数poll_wait把线程挂入队列,如果线程已经在队列里了,它就不会再次挂入。

② 返回设备状态:

APP调用poll函数时,有可能是查询“有没有数据可以读”:POLLIN,也有可能是查询“你有没有空间给我写数据”:POLLOUT。

所以drv_poll要返回自己的当前状态:(POLLIN | POLLRDNORM) 或 (POLLOUT | POLLWRNORM)。

POLLRDNORM等同于POLLIN,为了兼容某些APP把它们一起返回。

POLLWRNORM等同于POLLOUT ,为了兼容某些APP把它们一起返回。

APP调用poll后,很有可能会休眠。对应的,在按键驱动的中断服务程序中,也要有唤醒操作。

驱动程序中poll的代码如下:

static unsigned int gpio_key_drv_poll(struct file *fp, poll_table * wait)

{

printk("%s %s line %dn", __FILE__, __FUNCTION__, __LINE__);

poll_wait(fp, &gpio_key_wait, wait);

return is_key_buf_empty() ? 0 : POLLIN | POLLRDNORM;

}

19.2.4 应用编程

注意:APP可以调用poll或select函数,这2个函数的作用是一样的。

poll/select函数可以监测多个文件,可以监测多种事件:

事件类型

说明

POLLIN

有数据可读

POLLRDNORM

等同于POLLIN

POLLRDBAND

Priority band data can be read,有优先级较较高的“band data”可读

Linux系统中很少使用这个事件

POLLPRI

高优先级数据可读

POLLOUT

可以写数据

POLLWRNORM

等同于POLLOUT

POLLWRBAND

Priority data may be written

POLLERR

发生了错误

POLLHUP

挂起

POLLNVAL

无效的请求,一般是fd未open

在调用poll函数时,要指明:

① 你要监测哪一个文件:哪一个fd

② 你想监测这个文件的哪种事件:是POLLIN、还是POLLOUT

最后,在poll函数返回时,要判断状态。

应用程序代码如下:

struct pollfd fds[1];

int timeout_ms = 5000;

int ret;

fds[0].fd = fd;

fds[0].events = POLLIN;

ret = poll(fds, 1, timeout_ms);

if ((ret == 1) && (fds[0].revents & POLLIN))

{

read(fd, &val, 4);

printf("get button : 0x%xn", val);

}

19.2.5 现场编程

看视频

19.2.6 上机实验

看视频

19.2.7 POLL机制的内核代码详解

Linux APP系统调用,基本都可以在它的名字前加上“sys_”前缀,这就是它在内核中对应的函数。比如系统调用open、read、write、poll,与之对应的内核函数为:sys_open、sys_read、sys_write、sys_poll。

对于系统调用poll或select,它们对应的内核函数都是sys_poll。分析sys_poll,即可理解poll机制。

19.2.7.1 sys_poll函数

sys_poll位于fs/select.c文件中,代码如下:

SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,

int, timeout_msecs)

{

struct timespec64 end_time, *to = NULL;

int ret;

if (timeout_msecs >= 0) {

to = &end_time;

poll_select_set_timeout(to, timeout_msecs / MSEC_PER_SEC,

NSEC_PER_MSEC * (timeout_msecs % MSEC_PER_SEC));

}

ret = do_sys_poll(ufds, nfds, to);

……

SYSCALL_DEFINE3是一个宏,它定义于include/linux/syscalls.h,展开后就有sys_poll函数。

sys_poll对超时参数稍作处理后,直接调用do_sys_poll。

19.2.7.2 do_sys_poll函数

do_sys_poll位于fs/select.c文件中,我们忽略其他代码,只看关键部分:

int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,

struct timespec64 *end_time)

{

……

poll_initwait(&table);

fdcount = do_poll(head, &table, end_time);

poll_freewait(&table);

……

}

poll_initwait函数非常简单,它初始化一个poll_wqueues变量table:

poll_initwait

init_poll_funcptr(&pwq->pt, __pollwait);

pt->qproc = qproc;

即table->pt->qproc = __pollwait,__pollwait将在驱动的poll函数里用到。

do_poll函数才是核心,继续看代码。

19.2.7.3 do_poll函数

do_poll函数位于fs/select.c文件中,这是POLL机制中最核心的代码,贴图如下:

① 从这里开始,将会导致驱动程序的poll函数被第一次调用。

沿着②③④⑤,你可以看到:驱动程序里的poll_wait会调用__pollwait函数把线程放入某个队列。

当执行完①之后,在⑥或⑦处,pt->_qproc被设置为NULL,所以第二次调用驱动程序的poll时,不会再次把线程放入某个队列里。

⑧ 如果驱动程序的poll返回有效值,则count非0,跳出循环;

⑨ 否则休眠一段时间;当休眠时间到,或是被中断唤醒时,会再次循环、再次调用驱动程序的poll。

回顾APP的代码,APP可以指定“想等待某些事件”,poll函数返回后,可以知道“发生了哪些事件”:

驱动程序里怎么体现呢?在上上一个图中,看②位置处,细说如下:

-☆ END ☆-

我是韦东山,10多年一直在研究linux+ARM,希望我的分享对你有帮助,欢迎进店订阅我的付费内容:http://100ask.taobao.com

欢迎加群与韦老师交流讨论:

c++ linux 线程等待与唤醒_Linux驱动程序基石-POLL机制(附.视频)相关推荐

  1. c++ linux 线程等待与唤醒_Linux线程同步(互斥量、信号量、条件变量、生产消费者模型)...

    为什么要线程同步? 线程间有很多共享资源,都对一个共享数据读写操作,线程操作共享资源的先后顺序不确定,可能会造成数据的冲突 看一个例子 两个线程屏行对全局变量count++ (采用一个val值作为中间 ...

  2. c++ linux 线程等待与唤醒_C++ Linux线程同步机制:POSIX信号量,互斥锁,条件变量...

    线程同步机制:POSIX 信号量,互斥量,条件变量 POSIX 信号量 常用的POSIX 信号量函数为如下5个: sem_init sem_destroy sem_wait sem_trywait s ...

  3. c++ linux 线程等待与唤醒_C++并发编程 等待与唤醒

    C++并发编程 等待与唤醒 条件变量 条件变量, 包括(std::condition_variable 和 std::condition_variable_any) 定义在 condition_var ...

  4. Windows事件等待学习笔记(二)—— 线程等待与唤醒

    Windows事件等待学习笔记(二)-- 线程等待与唤醒 要点回顾 等待与唤醒机制 可等待对象 可等待对象的差异 线程与等待对象 一个线程等待一个对象 实验 第一步:编译并运行以下代码 第二步:在Wi ...

  5. java队列等待唤醒_Java深入学习29:线程等待和唤醒的两个方案

    Java深入学习29:线程等待和唤醒的两个方案 模拟场景 一个门店,有一个店员,有消费者来消费商品(每次消费1件商品),有仓库人员来添加(生产)商品(每次生产1件商品),并假设库存上限是2. 基础代码 ...

  6. C++多线程:Linux 线程通信,唤醒,互斥锁(未完待续)

    c++ multi thread message sending and notify 线程通信常用的方法有共享内存和消息传递,推荐使用消息传递. 最常用的就是管道了,可以使用匿名管道或者命名管道. ...

  7. 字符设备驱动程序之poll机制

    前面的按键中断驱动,只能实现当有按键按下的时候,输出,平时cpu处于休眠状态.如果我想实现,休眠一段时间执行一些指令,当有中断发生时,cpu又可以立即响应.那就得用poll机制. poll机制分析 韦 ...

  8. 字符设备驱动程序之poll机制(韦大仙)

    明确为什么要引用poll机制? while(1) { read(fd,&key_val,1);//如果没有按键按下,它会一直在等待.现在想做这么一件事情:如果5s后,没有按键按下,它就会返回. ...

  9. 韦东山驱动视频笔记——3.字符设备驱动程序之poll机制

    linux内核版本:linux-2.6.30.4 目的:我们在中断方式的按键应用程序中,如果没有按键按下,read就会永远在那等待,所以如果在这个程序里还想做其他事就不可能了.因此我们这次改进它,让它 ...

最新文章

  1. SWIG,C#沟通C++的桥梁
  2. 穿透Session 0 隔离(一)
  3. ubuntu安装node.js
  4. Java基础知识强化26:Object类之hashCode()方法、getClass()方法
  5. CSS 选择器权重计算规则
  6. print的小白用法
  7. 通过NodeJS自动生成的MySQL的REST风格API
  8. 谷歌大脑AutoML最新进展:不断进化的阿米巴网络
  9. Solaris下用Bind安装和配置DNS
  10. Excel生成指定范围内随机数
  11. java实现消息推送_java实现后台服务器消息推送
  12. Linux系统下,redis集群的搭建
  13. 【问题解决】error: pathspec ‘XXX‘ did not match any file(s) known to git
  14. linux限制message日志大小,message显示rsyslog日志服务警告信息due to rate-limiting
  15. 锅炉实现物联网云平台方案
  16. Java程序员 面试如何介绍项目经验? Java程序员应该如何介绍自己的项目经验和自我介绍?面试如何突出自己
  17. matlab去除图像背景,从图像中移除背景(首选MATLAB、Java或Python)
  18. 酷狗的krc歌词文件的解析
  19. 赚钱的方式,很有道理!!!!
  20. 测试老江湖告诉你,测试猿如何优雅的甩锅?

热门文章

  1. 如何使用ES6在JavaScript中有条件地构建对象
  2. 如何破解Mac并为其提供真正应得的精美壁纸
  3. docker下使用mongodb
  4. centos mysql安装
  5. Python高级——正则表达式与re模块
  6. python3中import的那么些坑
  7. Python hashlib模块中的sha加密
  8. CSS hack技巧大全 案例演示
  9. PRML-系列一之1.2.4
  10. leetcode - 39. 组合总和