驱动学习(十)poll机制

文章目录

  • 驱动学习(十)poll机制
    • 1. io多路复用思想:
    • 2. 驱动如何实现poll机制呢?
    • 3.测试
1. io多路复用思想:
1 构建一张文件描述符集合表 fd_set stfdr;//1024bit1024Bit用来存放1024个文件描述符对应的IO通道上是否有数据?有数据,该位为1;无数据,该位为0。
2 select 用来监控指定范围的文件描述符上是否有数据发生?若有数据发生,select返回有数据发生的通道个数;同时将有数据发生的文件描述符对应的集合表相应BIT置为1,并将其他Bit置0(监控 置位)
3 对文件描述符集合表的置位结果做判断并响应FD_ISSET(i,&stfdr)
2. 驱动如何实现poll机制呢?
应用层: fd=open("/dev/设备文件名",)selectread/write
驱动层:需要实现对应的Poll函数
1 将监控文件描述符的进程放入监控队列中poll_wait(pFile,&q,ptable)ptable:轮询表(将当前操作文件描述符的进程加入到休眠等待队列中,将该队列加到ptable中)
2 系统对监控队列中的进程监控,若被监控的进程上的文件描述符对应的通道有IO数据发生,系统会将该进程激活-->return mask;mask:是用来描述操作是否可以立即无阻塞执行的位掩码是一个32bits的整数,它的每个bit都代表了设备的一种状态(每个bit位都可以用一个宏来表示)POLLIN:有数据可读POLLRDNORM:有普通数据可读POLLOUT:有数据可写POLLERR:指定文件描述符发生错误
3.测试

代码

###### poll.c#include <linux/module.h>           //模块驱动的头文件
#include <linux/cdev.h>             //设备信息描述的头文件
#include <linux/fs.h>               //静态申请设备号头文件
#include <linux/kdev_t.h>           //设备号用到的头文件和宏函数
#include <linux/uaccess.h>
#include <linux/device.h>
#include "common.h"
#include <linux/sched.h>
#include <linux/poll.h>#define BUF_SIZE 100int major = 0;                      //主设备号
int min = 0;                        //次设备号
int deviceNum = 0;                  //完整设备号
struct cdev* pCdev = NULL;          //描述设备信息的结构体
char *deviceName = "poll";//设备名
char buff[BUF_SIZE] = "chrdev-test-2022-7-14";
struct class *pClass = NULL;        //设备文件类指针
int devNum = 2;                    //设备文件数量
wait_queue_head_t q;                //定义休眠等待队列头
int con = 0;                        //休眠唤醒条件 1唤醒 0休眠
int charCount = 0;                  //实际写入字符数量
int testOpen(struct inode *pNode,struct file *pFile)
{printk("------into test open------\n");con = 0;printk("------leave test open------\n");return 0;
}
int testClose(struct inode *pNode,struct file *pFile)
{printk("------into test close------\n");printk("------leave test close------\n");return 0;
}
ssize_t testRead(struct file *pFile,char __user *buf,size_t count,loff_t *pOffset)
{int res = -1;printk("------into testRead------\n");if(charCount <= 0){if(pFile->f_flags&O_NONBLOCK){printk("O_NONBLOCK is setted\n");return -EAGAIN;}else{wait_event_interruptible(q,con);}}if(count > BUF_SIZE-1){count = BUF_SIZE - 1;}if(count > charCount){count = charCount;}res = copy_to_user(buf,buff,count);if(res){printk("copy_to_user error\n");return -EFAULT;}charCount -= count;printk("copy_to_user ok\n");printk("\t buff = %s\t\n",buff);printk("------leave testRead------\n");return count;
}ssize_t testWrite(struct file *pFile,const char __user *buf,size_t count,loff_t *pOffset)
{int res = -1;printk("------into testWrite------\n");con = 1;wake_up_interruptible(&q);if(count > BUF_SIZE-1){count = BUF_SIZE - 1;}res = copy_from_user(buff,buf,count);if(res){printk("copy_from_user error\n");return -EFAULT;}charCount = count;printk("copy_from_user ok\n");printk("\t buff = %s\t\n",buff);printk("------leave testWrite------\n");return count;
}long testIoctl(struct file *pFile,unsigned int cmd,unsigned long arg)
{switch(cmd){case TEST_CMD:{printk("test cmd-------arg = %ld \n",arg);}break;case TEST_CMD1:{printk("test cmd1-------arg = %ld \n",arg);}break;case TEST_CMD2:{printk("test cmd2-------arg = %ld \n",arg);}break;default:printk("error cmd \n");}return 0;
}
unsigned int testPoll(struct file *pFile,struct poll_table_struct *ptable)
{unsigned int mask = 0;printk("into testpoll\n");poll_wait(pFile,&q,ptable);if(charCount > 0){printk("read mask id setted \n");mask = POLLIN|POLLRDNORM;}printk("leave testpoll \n");return mask;
}struct file_operations fp_arr =
{.owner = THIS_MODULE,.open = testOpen,.read = testRead,.write = testWrite,.release = testClose,.unlocked_ioctl = testIoctl,.poll = testPoll
};int driverr_init(void)               //模块初始化函数
{int res = 0;int i = 0;struct device *pDevTmp = NULL;printk("*********into driver init\n");//动态申请设备号res = alloc_chrdev_region(&deviceNum,min,devNum,deviceName);if(res){printk("alloc_chrdev_region error\n");return res;}printk("alloc_chrdev_region OK!\n");printk("major = %d minor = %d \n",MAJOR(deviceNum),MINOR(deviceNum));major = MAJOR(deviceNum);//创建设备pCdev = cdev_alloc();if(NULL == pCdev){printk("cdev_alloc error\n");unregister_chrdev_region(deviceNum,devNum);return -1;}printk("cdev_alloc ok\n");//设备初始化cdev_init(pCdev,&fp_arr);printk("cdev_init ok\n");//设备与设备号关联res = cdev_add(pCdev,deviceNum,devNum);if(res){printk("cdev_add error\n");cdev_del(pCdev);}printk("cdev_add ok\n");//创建设备文件类pClass = class_create(THIS_MODULE,"poll");if(NULL == pClass){printk("class_create error\n");cdev_del(pCdev);}printk("class_create ok\n");//创建设备文件for(;i < devNum;i++){pDevTmp = device_create(pClass,NULL,MKDEV(major,i),NULL,"poll%d",i);if(IS_ERR(pDevTmp)){printk("device_create error\n");for(i = 0;i < devNum;i++){device_destroy(pClass,MKDEV(major,i));}class_destroy(pClass);return -2;}}printk("device_create ok\n");//初始化休眠等待队列init_waitqueue_head(&q);printk("init_waitqueue_head ok\n");printk("*********leave driver init\n");return 0;
}void driver_clear(void)             //模块清除函数
{int i = 0;printk("*********into driver clear\n");for(;i < devNum; i++){device_destroy(pClass,MKDEV(major,i));}class_destroy(pClass);cdev_del(pCdev);unregister_chrdev_region(deviceNum,devNum);printk("*********leave driver clear\n");
}module_init(driverr_init);           //模块加载函数
module_exit(driver_clear);          //模块卸载函数MODULE_LICENSE("GPL");
MODULE_AUTHOR("cfy");
MODULE_ALIAS("liangzai");
MODULE_DESCRIPTION("2022-7-14");
##### test.c#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>#define BUF_SIZE 100int main()
{int fd = open("/dev/poll0",O_RDWR);if(fd < 0){printf("open poll0 err\n");return -1;}printf("open poll0 ok\n");fd_set stfdr;char buf[BUF_SIZE] = {0};int res = -1;while(1){FD_ZERO(&stfdr);FD_SET(fd,&stfdr);res = select(fd+1,&stfdr,NULL,NULL,NULL);if(res <= 0){continue;}if(FD_ISSET(fd,&stfdr)){//测试读bzero(buf,sizeof(buf));read(fd,buf,BUF_SIZE-1);printf("read data:%s\n",buf);}}close(fd);return 0;}
##### test1.c#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>#define BUF_SIZE 100int main()
{int fd = open("/dev/poll0",O_RDWR);if(fd < 0){printf("open poll0 err\n");return -1;}printf("open poll0 ok\n");char buf[BUF_SIZE] = {0};while(1){//测试写printf(">> input:");bzero(buf,sizeof(buf));scanf("%s",buf);write(fd,buf,sizeof(buf));}close(fd);return 0;}

现象

安装驱动模块,运行测试程序,此时test未读到数据,说明驱动中MASK的值不是POLLIN或者POLLRDNORM

在test1中写入数据,可以看到test读到了数据

结论

poll机制测试成功,虽然没有看到read不是无脑阻塞,而是因为select通过驱动的poll收到了POLLIN或者是POLLRDNORM而调用的read,emmm,没问题!

在测试的过程中突然想到就一个设备文件,为什么要使用select呢?不如直接阻塞啊,阻塞还能让进程放弃cpu的资源呢,select遍历加轮询不是占用资源嘛,还是有点尬的,这是个测试,只是打开了一个设备文件,调用了多个驱动后就有意义了啊!

驱动学习(十)poll机制相关推荐

  1. linux 内核驱动的poll,Linux驱动基石之POLL机制

    来源:百问网 作者:韦东山 本文字数:2344,阅读时长:4分钟 1.适用场景 在前面引入中断时,我们曾经举过一个例子: 妈妈怎么知道卧室里小孩醒了? 时不时进房间看一下:查询方式 简单,但是累 进去 ...

  2. linux v4l2系统详解,Linux摄像头驱动学习之:(一)V4L2_框架分析

    这段时间开始搞安卓camera底层驱动了,把以前的的Linux视频驱动回顾一下,本篇主要概述一下vfl2(video for linux 2). 一. V4L2框架: video for linux ...

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

    今天<升级版全系列嵌入式视频_入门篇>新增一节视频:19.2_POLL机制 时长24分钟,免费观看 何为POLL机制? 给驱动程序加一个闹钟,让APP不必死等数据: 既可以快速掌握 POL ...

  4. 从零开始之驱动发开、linux驱动(十六、poll机制)

    上一节分析了系统调用函数的封装,这一节我们学习一下poll系统调用函数.就从最开始的sys_poll开始. 在开始之前我们先了解一下poll函数的作用. 使用下面命令查看poll的使用方法和作用可知 ...

  5. linux 内核驱动的poll,嵌入式Linux驱动开发(五)——poll机制原理以及驱动实现...

    前情回顾: 再开始今天的内容之前,先简单review一下,我们都用了什么方案来获取按键值,他们的特点都是什么.只有不断地理清了思路,我们才能够更好的理解,为何会出现如此多的解决方案,当遇到问题的时候, ...

  6. Linux驱动开发(十八)---网络(网卡)驱动学习

    前文回顾 <Linux驱动开发(一)-环境搭建与hello world> <Linux驱动开发(二)-驱动与设备的分离设计> <Linux驱动开发(三)-设备树> ...

  7. linux 内核驱动的poll,详细解读Linux内核的poll机制

    所有的系统调用,基于都可以在它的名字前加上"sys_"前缀,这就是它在内核中对应的函数.比如系统调用open.read.write.poll,与之对应的内核函数为:sys_open ...

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

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

  9. LSTM 之父发文:2010-2020,我眼中的深度学习十年简史

    作者 | Jürgen Schmidhuber 译者 | 刘畅.若名 出品 | AI科技大本营(ID:rgznai100) 作为LSTM发明人.深度学习元老,Jürgen Schmidhuber于2月 ...

最新文章

  1. Redis解决websocket在分布式场景下session共享问题
  2. 挑选适合自己的公司——网络工程师你是否真的已经倒下(二)
  3. template might not exist or might not be accessible by any of the configured Template Resolvers
  4. randaugment
  5. boost::boyer_myrvold_params::kuratowski_subgraph用法的测试程序
  6. 宏BOOST_TEST_REF的用法程序
  7. matlab 计算大圆距离,已知两点经纬度计算两点之间的大圆距离
  8. 牛客练习赛89--牛牛防疫情
  9. 线性代数不深入,机器学习两行泪!
  10. python中表示空类型的是_python中什么表示空类型
  11. img默认图片的问题
  12. 最常见的Java框架有哪些?
  13. Linux-v10-01天-授课
  14. pdf签名无效解决办法_谁告诉你PDF不能修改了?我不仅可以直接编辑,还能随便转化格式!...
  15. python机构换手率_46只业绩翻倍+机构重仓芯片潜力股(名单)一览,换手率大于10...
  16. C语言考试题库之填空题
  17. wlop2020全奖励包_【图包】WLOP鬼刀壁纸【更新至2020年10月】
  18. JavaScript原型链实现继承
  19. bergerAimi
  20. [转]键盘上的符号用英语怎么读?

热门文章

  1. 快递查询方法一键查询物流信息
  2. 云时代编程语言Ballerina发布,TIOBE9月排行榜PHP排名在边缘飘摇(2019/09/16)
  3. 华为手机计算机如何表达平方,华为手机郑平方:荣耀成功源于共享质量体系
  4. Debian 支持蓝牙音响
  5. I.MX6 AW-NB177NF wifi HAL 调试修改
  6. vue父组给子子组件传html,vue组件之间互相传值:父传子,子传父
  7. 将win7 firefox WebStorm PyCharm等JetBrains系列开发软件设置为豆沙绿护眼背景
  8. Word学习简单笔记(2)文档排版与设计
  9. BNUZ自动打卡系统
  10. Phun-有趣的二维物理引擎