UIO(Userspace I/O)是运行在用户空间的I/O技术。在Linux系统中,一般的设备驱动都是运行在内核空间,而在用户空间使用应用程序调用即可。而UIO则是将设备驱动的很少一部分运行在内核空间,而在用户空间实现驱动的绝大多数功能。那么,在内核空间UIO要做的事情就变得很简单,分为两种:
分配和记录设备需要的资源和注册UIO设备
实现必须在内核空间实现的中断处理函数
为了对UIO有一个直观的认识,先上个图:
了解了UIO 驱动在Linux系统中的位置后,让我们对参考资料(Linux User Space Device Drivers)的部分内容做一个中英文对照翻译以加深对UIO的理解。
Linux device drivers are typically designed as kernel drivers running in kernel space 典型的Linux设备驱动都是被设计为运行在内核空间的内核驱动
User space I/O is another alternative device driver architecture that has been supported by the Linux kernel since 2.6.24 从Linux内核版本2.6.24开始,就支持另一种可作为内核设备驱动的替代方案的设备驱动架构,也就是用户空间I/O
People in the Linux kernel community may not always agree on the need to have user space I/O 在Linux内核社区的人们不总是赞成使用用户空间I/O
Industrial I/O cards have been taking advantage of user space I/O for quite some time 在工业中使用的I/O卡利用用户空间I/O的优点已经有一阵子了
For some types of devices, creating a Linux kernel driver may be overkill 对某些类型的设备来说,创建对应的Linux内核驱动很可能代价太高
Soft IP for FPGAs can have unique requirements that don't always fit the mold FPGA的软IP有独特的需求,将驱动放在内核实现并不总是适合的
内核中存在一个称为 /dev/mem 的字符驱动程序,它将设备内存映射到用户空间
有了这个驱动,用户空间应用程序可以访问设备内存
可以在内核配置中禁用内存访问,因为这是一个很大的安全漏洞 (CONFIG_STRICT_DEVMEM)
必须是root用户
用于原型设计或测试新硬件的好工具,但不被认为是用户空间设备驱动程序可接受的生产解决方案
由于它可以将任何地址映射到用户空间,因此有缺陷的用户空间驱动程序可能会使内核崩溃
Linux内核提供了一个框架来做用户空间驱动,叫做UIO
该框架是一个字符模式内核驱动程序(在驱动程序/uio 中),它作为一个层在用户空间驱动程序下运行
UIO 有助于卸载一些开发驱动程序的工作
UIO 中的“U”不是通用的
- 由内核框架处理好的设备最好留在内核中(如果您询问许多内核开发人员)
- 网络是半导体供应商进行用户空间 I/O 以提高性能的领域之一
UIO 可以很好地处理简单的设备驱动程序
- 简单的驱动:设备访问和中断处理,无需访问内核框架
以最高权限模式在内核空间中运行,以允许访问中断和硬件资源
有很多内核服务,可以为复杂的设备设计内核空间驱动程序
内核为用户空间提供 API,允许多个应用程序同时访问内核空间驱动程序
- 可以构建更大、更具可扩展性的软件系统
许多驱动程序往往是内核空间
- 在开源社区中提问会更容易
- 将驱动程序推送到开源社区可能更容易
访问驱动程序的系统调用开销
- 需要从用户空间切换到内核空间(并返回)
- 开销可能是不确定的,会对实时应用程序产生影响
开发人员具有挑战性的学习曲线
- 内核 API 与应用程序级 API 不同,因此需要时间才能变得高效
错误可能是致命的,导致内核崩溃
难以调试
- 内核代码高度优化,有不同的调试工具
频繁的内核 API 更改
- 为一个内核版本构建的内核驱动程序可能无法为另一个版本构建
由于调试工具更容易获得并且对于正常的应用程序开发来说更常见,因此调试的挑战更小
浮点等用户空间服务可用
设备访问非常有效,因为不需要系统调用
Linux的应用API非常稳定
驱动程序可以用任何语言编写,而不仅仅是“C”
无法访问内核框架和服务
- 连续内存分配、直接缓存控制和 DMA 不可用
- 可能必须复制内核代码或使用内核驱动程序来补充
中断处理不能在用户空间完成
- 它必须由通知用户空间导致一些延迟的内核驱动程序处理
没有预定义的 API 允许应用程序访问设备驱动程序
- 如果多个应用程序访问一个驱动程序,还必须考虑并发性
Linux 在 drivers/uio 中提供了两个不同的 UIO 设备驱动程序
UIO 驱动程序 (drivers/uio.c)
- 对于更高级的用户,因为需要最小的内核空间驱动程序来设置 UIO 框架
- 这是最通用的并且可能处理所有情况,因为内核空间驱动程序可以非常自定义
- 大部分工作都可以在用户空间驱动程序中完成
UIO 平台设备驱动程序 (drivers/uio_pdev_irqgen.c)
此驱动程序增强了 UIO 驱动程序,因此不需要内核空间驱动程序
它为 uio 提供了所需的内核空间驱动程序
它与设备树一起使用,使其易于使用
设备的设备树节点需要使用“通用 uio”在它的兼容
最佳起点,因为不需要内核空间代码
UIO 驱动程序必须在 Linux 内核中配置
- CONFIG_UIO=y
- CONFIG_UIO_PDRV_GENIRQ=y
用户只提供一个用户空间驱动
UIO平台设备驱动从设备树配置并注册一个UIO设备
用户空间驱动程序可以直接访问硬件
用户空间驱动程序通过读取 UIO 设备文件描述符获得中断通知
内核中的 UIO 驱动程序在描述 UIO 设备的 sys 文件系统中创建文件属性
/sys/class/uio 是所有文件属性的根目录
在 /sys/class/uio 下为每个 UIO 设备创建一个单独的编号目录结构
- 第一个 UIO 设备:/sys/class/uio/uio0
- /sys/class/uio/uio0/name 包含与 uio_info 结构中的名称相关的设备名称
- /sys/class/uio/uio0/maps 是一个包含设备所有内存范围的目录
- 每个编号的映射目录都有描述设备内存的属性,包括地址、名称、偏移量和大小
/sys/class/uio/uio0/maps/map0
01 - 内核空间 UIO 设备驱动程序必须在用户空间驱动程序启动之前加载(如果使用模块)
02 - 启动用户空间应用程序并打开 UIO 设备文件(/dev/uioX 其中 X 为 0、1、2 ...)
- 从用户空间来看,UIO 设备是文件系统中的一个设备节点,就像任何其他设备一样
03 - 设备内存地址信息从相关的sysfs目录中找到,只需要大小
04 - 通过调用UIO驱动的mmap()函数将设备内存映射到进程地址空间
05 - 应用程序访问设备硬件来控制设备
06 - 通过调用 munmap() 取消映射设备内存
07 - UIO设备文件关闭
- #define UIO_SIZE "/sys/class/uio/uio0/maps/map0/size"
-
- int main( int argc, char ** argv)
- {
- int uio_fd;
- 无符号整数 uio_size;
- 文件 *大小_fp;
- 无效 *基地址;
-
- /*
- * 1. 打开 UIO 设备,使其可以使用
- */
- uio_fd = open( " /dev/uio0" , O_RDWR);
-
- /*
- * 2. 从大小 sysfs 文件中获取内存区域的大小
- * 属性
- */
- size_fp = fopen(UIO_SIZE, O_RDONLY);
- fscanf(size_fp, " 0x%08X " , & uio_size);
-
- /*
- * 3. 将设备寄存器映射到进程地址空间,以便它们
- * 可直接访问
- */
- base_address =mmap(NULL, uio_size,
- PROT_READ| PROT_WRITE,
- MAP_SHARED, uio_fd, 0 );
-
- // 现在可以访问硬件 ...
-
- /*
- * 4. 取消映射设备寄存器以完成
- */
- munmap(base_address, uio_size);
-
- ...
- }
原文链接:https://www.cnblogs.com/vlhn/p/7761869.html
更多DPDK学习资料有需要的可以自行添加进入学习交流君 羊 793599096 免费获取,或自行报名学习,免费订阅,永久学习,关注我持续更新哦!!!
学习地址:http://ke.qq.com/course/5066203?flowToken=1043717