linux驱动poll机制简要介绍是什么
发表于:2024-11-20 作者:千家信息网编辑
千家信息网最后更新 2024年11月20日,本篇文章给大家分享的是有关linux驱动poll机制简要介绍是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。#include #in
千家信息网最后更新 2024年11月20日linux驱动poll机制简要介绍是什么
本篇文章给大家分享的是有关linux驱动poll机制简要介绍是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
#include#include #include #include #include #include #include #include #include #include #include #include static struct class *forthdrv_class;static struct class_device *forthdrv_class_dev;volatile unsigned long *gpfcon;volatile unsigned long *gpfdat;volatile unsigned long *gpgcon;volatile unsigned long *gpgdat;static DECLARE_WAIT_QUEUE_HEAD(button_waitq);/* 中断事件标志, 中断服务程序将它置1,forth_drv_read将它清0 */static volatile int ev_press = 0;struct pin_desc{ unsigned int pin; unsigned int key_val;};/* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 *//* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 */static unsigned char key_val;struct pin_desc pins_desc[4] = { {S3C2410_GPF0, 0x01}, {S3C2410_GPF2, 0x02}, {S3C2410_GPG3, 0x03}, {S3C2410_GPG11, 0x04},};/* * 确定按键值 */static irqreturn_t buttons_irq(int irq, void *dev_id){ struct pin_desc * pindesc = (struct pin_desc *)dev_id; unsigned int pinval; //这里怎么知道是哪个引脚触发的中断? 这里并不判断是哪个按键产生的中断, 如果要获取当前的中断号可以打印 irq 参数来查看 pinval = s3c2410_gpio_getpin(pindesc->pin);//该函数返回GPxDAT的值, 如GPF9则返回 0X100(剩余位被mask), 而不是 1 if (pinval) { /* 松开 */ key_val = 0x80 | pindesc->key_val; } else { /* 按下 */ key_val = pindesc->key_val; } ev_press = 1; /* 表示中断发生了 */ wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */ return IRQ_RETVAL(IRQ_HANDLED);}static int forth_drv_open(struct inode *inode, struct file *file){ /* 配置GPF0,2为输入引脚 */ /* 配置GPG3,11为输入引脚 */ request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, "S2", &pins_desc[0]); request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, "S3", &pins_desc[1]); request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "S4", &pins_desc[2]); request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, "S5", &pins_desc[3]); return 0;}ssize_t forth_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos){ if (size != 1) return -EINVAL; /* 如果没有按键动作, 休眠 */ wait_event_interruptible(button_waitq, ev_press); /* 如果有按键动作, 返回键值 */ copy_to_user(buf, &key_val, 1); ev_press = 0; return 1;}int forth_drv_close(struct inode *inode, struct file *file){ free_irq(IRQ_EINT0, &pins_desc[0]); free_irq(IRQ_EINT2, &pins_desc[1]); free_irq(IRQ_EINT11, &pins_desc[2]); free_irq(IRQ_EINT19, &pins_desc[3]); return 0;}static unsigned forth_drv_poll(struct file *file, poll_table *wait){ unsigned int mask = 0; poll_wait(file, &button_waitq, wait); // 不会立即休眠 if (ev_press) mask |= POLLIN | POLLRDNORM; return mask;}static struct file_operations sencod_drv_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = forth_drv_open, .read = forth_drv_read, .release = forth_drv_close, .poll = forth_drv_poll,};int major;static int forth_drv_init(void){ major = register_chrdev(0, "forth_drv", &sencod_drv_fops); forthdrv_class = class_create(THIS_MODULE, "forth_drv"); forthdrv_class_dev = class_device_create(forthdrv_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */ gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16); gpfdat = gpfcon + 1; gpgcon = (volatile unsigned long *)ioremap(0x56000060, 16); gpgdat = gpgcon + 1; return 0;}static void forth_drv_exit(void){ unregister_chrdev(major, "forth_drv"); class_device_unregister(forthdrv_class_dev); class_destroy(forthdrv_class); iounmap(gpfcon); iounmap(gpgcon); return 0;}module_init(forth_drv_init);module_exit(forth_drv_exit);MODULE_LICENSE("GPL");/*poll 执行的步骤 : poll 分析:应用程序:poll sys_poll do_sys_poll poll_initwait(&table) init_poll_funcptr(&pwq->pt, __pollwait) >> table->pt->qproc = __pollwait; 据说 xxx_fops->xxx_drv_poll 调中的 poll_wait 最后调用的就是 __pollwait 函数, 怎么看出来的? do_poll(nfds, head, &table, timeout) //遍历传入的所有描述符 for (;;) { //mask = file->f_op->poll(file, pwait); 这里的poll就是驱动里的 xxx_drv_poll(struct file *file, poll_table *wait), mask就是驱动中的返回值 if (do_pollfd(pfd, pt)) { count++; pt = NULL; } //如果驱动就绪返回非0值, 则跳出循环 if (count || !*timeout || signal_pending(current)) break; //如果未就绪或者且时间未到则休眠 schedule_timeout(__timeout); }例程执行过程:调用poll 1. 先注册 __pollwait 就是xxx_drv_poll 中 poll_wait 函数最终调用的内容 2. 然后调用 do_poll, 遍历传入的描述符, do_pollfd就是调用xxx_drv_poll, 它将本进程添加到驱动设置的等待队列中, 根据返回值来判断是否可以跳出do_poll循环, 如果没有就绪且没有超时则该进程睡眠. 如果发生中断,在中断中要设置中断标志并唤醒睡眠的进程. 唤醒之后仍旧从do_poll的死循环开始执行, 再次执行了驱动中的 xxx_drv_poll, 而这时已经可读则顺利返回非0 mask值. 如果是超时则执行xxx_drv_poll仍旧无有效mask值, 可以但可以直接跳出do_poll循环, 应用程序根据不同的mask值做处理*/
以上就是linux驱动poll机制简要介绍是什么,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。
驱动
就是
按键
进程
休眠
循环
函数
程序
机制
简要
动作
应用程序
更多
标志
知识
篇文章
应用
睡眠
输入
配置
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
军团要塞安全服务器
网络安全工程师培训班
韩国高防服务器优势
法律法规数据库建设的意义
电脑服务器主板品牌
免费的云数据库sdk
绿野仙踪下载软件开发
xcoder 数据库使用
局网络安全工作报告
数据库中年龄怎么计算
小程序服务器老是被攻击
搜一下河北网络安全周安全问答
软件开发计划438b
途强在线服务器连不上
vs数据库执行sql语句
电视能连上无线网但连不上服务器
清远嵌入式软件开发
宝塔账号密码数据库查看
力控 组态数据库 变量
连接不上惠普服务器
微软数据库资源管理器
软件开发首先需要学什么
深入宣传中央网络安全
如何组织一场网络安全比赛
大族的软件开发待遇怎么样
衡水财务软件开发费用
域名是不是什么服务器都可以
软件开发自学步骤视频教程
网络安全指挥中心和高校比较
阿里云服务器规则安全