linux驱动poll机制简要介绍是什么
发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,本篇文章给大家分享的是有关linux驱动poll机制简要介绍是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。#include #in
千家信息网最后更新 2025年12月02日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安全错误
数据库的锁怎样保障安全
我的世界服务器的矿洞
c 如何监听数据库变化
吸烟文献数据库有哪些
网络技术沙龙图片
服务器租用如何选择
新乡市鹏摇网络技术有限公司
db2新建数据库用户
宿州通信软件开发公司哪家好
linux修改数据库配置
pg数据库语法区别
黑莓q20 服务器
梦幻古龙数据库
数据库结果相加函数
服务器 便宜
城管局网络安全工作总结
自学云计算软件开发
广东计算机软件开发正规平台
武汉信息网络安全协会
dhcp服务器软件 免费
数据库为什么不能组合关键字
软件开发过程中来自用户
i7低耗软件开发
服务器不能连接电脑怎么办
新乡市鹏摇网络技术有限公司
ios 线程 数据库
网络安全委员会成员
2019软件开发语言排名
网络安全课后答案沈鑫
全省网络安全与信息化工作会议
飞机导航数据库格式