linux UIO
UIO(linux Userspace I/O子系统)用户空间设备驱动I/O技术介绍(由www.169it.com搜集整理) UIO(Userspace I/O)是运行在用户空间的I/O技术。Linux系统中一般的驱动设备都是运行在内核空间,而在用户空间用应用程...
UIO(linux Userspace I/O子系统)用户空间设备驱动I/O技术介绍(由www.169it.com搜集整理)
UIO(Userspace I/O)是运行在用户空间的I/O技术。Linux系统中一般的驱动设备都是运行在内核空间,而在用户空间用应用程序调用即可,而UIO则是将驱动的很少 一部分运行在内核空间,而在用户空间实现驱动的绝大多数功能!使用UIO可以避免设备的驱动程序需要随着内核的更新而更新的问题.通 过UIO的运行原理图可以看出,用户空间下的驱动程序比运行在内核空间的驱动要多得多,UIO框架下运行在内核空间的驱动程序所做的工作很简单,常做的只 有两个:分配和记录设备需要的资源和注册uio设备和必须在内核空间实现的小部分中断应答函数,经过实践表明后面的工作也是可以省略的!我们认为uio内 核空间的程序所做的越少越好,在用户空间能完成的我们就不需要放在内核空间做(比如说响应中断),这样假如内核有变化,uio框架中的驱动维护也是比较简 单。
Linux UIO 驱动模型(图)
uio驱动的内核部分,用户空间部分,和uio 框架以及内核内部函数的关系图
uio驱动重要的数据结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | struct uio_device { struct module *owner; struct device *dev; //在__uio_register_device中初始化 int minor; // 次设备id号,uio_get_minor atomic_t event; //中断事件计数 struct fasync_struct *async_queue; //该设备上的异步等待队列// // 关于 “异步通知“ //参见LDD3第六章 wait_queue_head_t wait; //该设备上的等待队列,在注册设备时(__uio_register_device)初始化 int vma_count; struct uio_info *info; // 指向用户注册的uio_info,在__uio_register_device中被赋值的 struct kobject *map_dir; struct kobject *portio_dir; }; /* * struct uio_info - UIO device capabilities * @uio_dev: the UIO device this info belongs to * @name: device name * @version: device driver version * @mem: list of mappable memory regions, size==0 for end of list * @port: list of port regions, size==0 for end of list * @irq: interrupt number or UIO_IRQ_CUSTOM * @irq_flags: flags for request_irq() * @priv: optional private data * @handler: the device's irq handler * @mmap: mmap operation for this uio device * @open: open operation for this uio device * @release: release operation for this uio device * @irqcontrol: disable/enable irqs when 0/1 is written to /dev/uioX */ struct uio_info { struct uio_device *uio_dev; // 在__uio_register_device中初始化 const char *name; // 调用__uio_register_device之前必须初始化 const char *version; //调用__uio_register_device之前必须初始化 struct uio_mem mem[MAX_UIO_MAPS]; struct uio_port port[MAX_UIO_PORT_REGIONS]; long irq; //分配给uio设备的中断号,调用__uio_register_device之前必须初始化 unsigned long irq_flags; // 调用__uio_register_device之前必须初始化 void *priv; // irqreturn_t (*handler)( int irq, struct uio_info *dev_info); //uio_interrupt中调用,用于中断处理 // 调用__uio_register_device之前必须初始化 int (*mmap)( struct uio_info *info, struct vm_area_struct *vma); //在uio_mmap中被调用, // 执行设备打开特定操作 int (*open)( struct uio_info *info, struct inode *inode); //在uio_open中被调用,执行设备打开特定操作 int (*release)( struct uio_info *info, struct inode *inode); //在uio_device中被调用,执行设备打开特定操作 int (*irqcontrol)( struct uio_info *info, s32 irq_on); //在uio_write方法中被调用,执行用户驱动的 //特定操作。 }; |
UIO的内核部分和用户空间的工作
内核空间
UIO的少量运行在内核空间的驱动所做的工作有哪些呢?
(1)分配和记录设备需要的资源和注册uio设备
在设备的探测函数中:
- 使能PCI 设备
- 申请资源
- 读取并记录配置信息
- 注册uio设备// uio_register_device()
// uio_8139d_pci_probe & uio_8139d_handler
(2)必须*在内核空间实现的小部分中断应答函数
用户空间的关键操作
1关键操作
2.响应硬件中断
1 2 3 4 5 6 7 8 9 | int32_t irq_count; int fd = open( "/dev/uio0" , O_RDWR); /* Map the register regions to proccess's virtual memspace */ void * access = mmap(NULL, 4096, // 寄存器的读写操作,可用过普通内存读写的方式完成 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); // [1] while (read(fd, &irq_count, 4) == 4) {[2] printf ( "Interrupt number %d\n" , irq_count); |
posted on 2016-03-09 11:28 szllq2000 阅读(2743) 评论(0) 编辑 收藏 举报
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库