UIO
简介
UIO(Userspace I/O,用户空间IO)是运行在用户空间的I/O技术。UIO将驱动的很少一部分运行在内核空间,而在用户空间实现驱动的绝大多数功能!使用UIO可以避免设备的驱动程序需要随着内核的更新而更新的问题。
优势
简单。用户态便于调测;
可以使用C++、Java等高级语言进行开发;
即便用户空间驱动程序挂了,也不会影响系统的正常运行。
工作原理
设备驱动主要完成2件事:
处理设备产生的硬中断和存取设备内存;
硬中断处理必须在内核空间进行,而设备内存的存取可以在用户空间进行。
UIO框架分为2部分:
内核部分: 主要实现硬件寄存器的内存映射及读写操作,
用户空间部分: 负责将UIO设备的uio_mem映射到本地,*实现用户空间程序能够访问硬件设备寄存器。
UIO驱动模型请参考图1所示:
实现原理
UIO内核部分
UIO内核驱动做的事情相对来说比较少,主要的任务是:
分配和记录设备所需的资源*(使能PCI设备、申请资源、读取并记录配置信息)、
注册UIO设备(uio_register_device())
实现硬中断处理函数。
接下来我们将从代码角度,重点介绍UIO内核驱动实现涉及的重要数据结构和调用的函数。
|
|
UIO用户空间部分
用户空间驱动主要完成2个关键任务:
响应硬件中断;
从存取设备内存。
下面将使用理论 + 代码对用户空间驱动的能力进行介绍。
响应硬中断通常有2种处理方式,
调用read(),*阻塞/dev/uioX,*当设备产生中断时,**read()**操作立即返回;
调用poll(),使用**select()*等待中断发生(select()有一个超时参数可用来实现有限时间内等待中断)。
下面用一段代码说明如何完成硬中断响应处理*(阻塞**/dev/uio0**,调用**read()**处理硬中断信号)。*
|
|
对于如何存取设备内存呢?通过读写/sys/class/uioX
下的各个文件(注册的UIO设备在该目录下),完成对设备内存的读写。
比如UIO设备为uio0,那么映射的设备内存将在/sys/class/uio/uio0/maps下,对该文件的读写就是对设备内存的读写。
下面用一段代码说明如何存取设备内存(将设备信息mmap到用户空间,用户空间程序便可直接操作设备内存空间)。
|
|
UIO涉及的函数
最后一章节,对UIO框架主要涉及函数定义及功能描述进行汇总,具体的内容请参考如下表信息。
函数定义 | 功能描述 |
---|---|
static int __init uio_init(void) | 申请字符设备号和设备,并注册到系统中,注册uio_class到系统中 |
staticvoid__exituio_exit(void) | 注销uio_class,注销字符设备编号和删除设备 |
static void release_uio_class(void) | 注销uio_class,注销字符设备编号和删除设备 |
static int init_uio_class(void) | 申请字符设备号和设备,并注册到系统中,注册uio_class到系统中 |
static int uio_major_init(void) | 申请字符设备编号和设备,并初始化 |
static void uio_major_cleanup(void) | 注销字符设备编号,删除设备 |
static int uio_open(struct inode *inode, struct file *filep) | 获得和次设备号关联的uio_device指针,创建一个辅助变量listener, 并调用info指向的uio_info结构中的open方法 |
static int uio_release(struct inode *inode, struct file *filep) | 调用uio_device的字段info指向的uio_info中的release方法,释放辅助结构体listener |
static int uio_fasync(int fd, struct file *filep, int on) | 管理uio_device的async_queue |
static unsigned int uio_poll(struct file *filep, poll_table *wait) | 使进程在传递到该系统调用的所有文件描述符对应的等待队列上等待,并返回一个是否可以立即无阻塞执行的位掩码 |
static ssize_t uio_read(struct file *filep, char __user *buf, size_t count, loff_t *ppos) | 复制uio设备中断事件计数器的值到用户空间 |
int __uio_register_device(struct module *owner, struct device *parent, struct uio_info *info) | 调用uio_info中注册的handler中断处理函数,对设备的中断事件计数器增一并通知各读进程,有数据可读 |
void uio_event_notify(struct uio_info *info) | “触发”一个中断事件,对设备的中断事件计数器增一,并通知各读进程,有数据可读 |
static ssize_t uio_write(struct file *filep, const char __user *buf,size_t count, loff_t *ppos) | 读取用户空间的值,并调用uio_device注册的irqcontrol函数 |
static int uio_mmap(struct file *filep, struct vm_area_struct *vma) | 对uio设备进行mmap处理 |