UIO 是 Linux 内核提供的一种将设备驱动部分逻辑移到用户空间的机制,特别适合需要快速开发或自定义 I/O 处理的场景。以下是 UIO 框架的全面解析:
一、UIO 核心架构
1.1 整体架构图
用户空间程序
├── /dev/uioX (控制接口)
├── /sys/class/uio/uioX (信息接口)
└── mmap()映射区域 (设备内存)
内核空间
├── UIO核心框架
│ ├── 中断处理
│ └── 设备管理
└── 具体设备驱动
├── 内存映射
└── 中断通知
1.2 关键数据结构
struct uio_info {
const char *name; // 设备名称
const char *version; // 驱动版本
struct uio_mem mem[MAX_UIO_MAPS]; // 内存映射区域
struct uio_port port[MAX_UIO_PORT_REGIONS];
long irq; // 中断号
unsigned long irq_flags; // 中断标志
int (*handler)(int irq, struct uio_info *dev_info); // 中断处理
void (*release)(struct uio_info *dev_info); // 释放回调
// ...
};
二、UIO 工作流程
2.1 初始化流程
static int example_uio_probe(struct platform_device *pdev)
{
struct uio_info *info;
// 1. 分配UIO信息结构
info = kzalloc(sizeof(*info), GFP_KERNEL);
// 2. 设置内存映射区域
info->mem[0].addr = phys_addr; // 设备物理地址
info->mem[0].size = resource_size(res);
info->mem[0].memtype = UIO_MEM_PHYS;
// 3. 设置中断处理
info->irq = irq;
info->irq_flags = IRQF_SHARED;
info->handler = example_handler; // 内核中断处理
// 4. 注册UIO设备
uio_register_device(&pdev->dev, info);
}
2.2 中断处理流程
硬件中断触发
→ 内核驱动handler() (可选)
→ UIO核心标记中断
→ 用户空间read()解除阻塞
→ 用户空间处理中断
→ write()确认处理完成
三、用户空间编程接口
3.1 基本操作
// 打开UIO设备
int uio_fd = open("/dev/uio0", O_RDWR);
// 获取设备信息
struct uio_info_t {
uint32_t version;
char name[32];
// ...
};
ioctl(uio_fd, UIO_GETINFO, &info);
// 内存映射
void *regs = mmap(NULL, size, PROT_READ|PROT_WRITE,
MAP_SHARED, uio_fd, 0);
3.2 中断处理示例
uint32_t count;
while (1) {
// 阻塞等待中断
read(uio_fd, &count, sizeof(count));
// 处理中断
process_interrupt();
// 确认中断处理完成
write(uio_fd, &count, sizeof(count));
}
四、UIO 设备类型
4.1 通用PCI UIO
# 加载通用PCI UIO驱动
modprobe uio_pci_generic
# 绑定设备
echo "8086 10fb" > /sys/bus/pci/drivers/uio_pci_generic/new_id
4.2 定制UIO驱动开发
static struct platform_driver example_uio_driver = {
.probe = example_uio_probe,
.remove = example_uio_remove,
.driver = {
.name = "example-uio",
.owner = THIS_MODULE,
},
};
五、高级特性
5.1 多内存区域支持
// 设置多个内存区域
info->mem[0].name = "registers";
info->mem[1].name = "buffer";
info->mem[1].addr = dma_addr;
info->mem[1].size = BUF_SIZE;
5.2 DMA 支持
// 用户空间DMA操作流程
1. 通过mmap映射DMA缓冲区
2. 配置设备DMA引擎
3. 启动传输后等待中断
六、调试与监控
6.1 系统信息查看
# 查看已注册UIO设备
ls /sys/class/uio/
# 查看设备内存区域
cat /sys/class/uio/uio0/maps/map0/{name,addr,size}
6.2 性能统计
# 中断计数监控
cat /proc/interrupts | grep uio
七、典型应用场景
快速原型开发:在用户空间验证硬件功能
高性能数据路径:结合DPDK/SPDK等框架
专用加速器:FPGA、智能网卡等设备
遗留设备支持:为旧硬件提供现代接口
八、与传统内核驱动的对比
特性UIO驱动传统内核驱动开发难度低高性能中高安全性低高功能完整性需用户空间补充完整热插拔支持有限完善
UIO 框架通过合理的责任划分,在保持系统稳定性的同时,为特定场景提供了高效的开发模式。正确使用 UIO 可以显著降低驱动开发复杂度,但需要特别注意用户空间驱动的安全性和稳定性问题。