Linux内核 -- UIO (User-space I/O) 简介与使用笔记

devtools/2024/12/27 20:28:55/

UIO (User-space I/O) 简介

UIO (User-space I/O) 是 Linux 内核提供的一种机制,用于简化设备驱动的开发。它将设备的硬件资源(如内存映射、中断等)通过简单的接口暴露给用户空间程序,从而使用户可以在用户空间编写复杂的设备逻辑,而内核只需完成基础的资源管理工作。


内核态作用与实现

UIO 内核态的作用
  1. 硬件资源管理
    • 提供设备内存映射支持,将设备寄存器或内存映射到用户空间。
    • 注册和处理硬件中断(可选)。
  2. 中断通知
    • 将设备硬件中断转发给用户空间程序。
UIO 内核态的实现步骤
  1. 定义设备信息结构
    使用 struct uio_info 定义设备信息,包括中断号、内存地址等。

    static struct uio_info my_uio_info = {.name = "my_device",.version = "1.0",.irq = 42,                      // 中断号(若不需要中断,可设置为 UIO_IRQ_NONE).irq_flags = IRQF_SHARED,       // 中断标志.handler = my_irq_handler,      // 中断处理函数(可选).mem[0].addr = 0x40000000,      // 物理地址.mem[0].size = 0x1000,          // 内存大小.mem[0].memtype = UIO_MEM_PHYS, // 内存类型
    };
    
  2. 注册设备
    使用 uio_register_device 注册设备信息:

    static int __init my_uio_init(void) {return uio_register_device(NULL, &my_uio_info);
    }static void __exit my_uio_exit(void) {uio_unregister_device(&my_uio_info);
    }module_init(my_uio_init);
    module_exit(my_uio_exit);
    MODULE_LICENSE("GPL");
    
  3. 实现中断处理函数(可选)
    如果需要支持硬件中断,需要实现中断处理逻辑:

    static irqreturn_t my_irq_handler(int irq, struct uio_info *dev_info) {return IRQ_HANDLED; // 通知内核中断已处理
    }
    
注意事项
  • 如果设备不需要中断功能,可以将 irq 设置为 UIO_IRQ_NONE,并省略 handler
  • 内核态代码只需要完成资源管理工作,具体设备逻辑由用户空间程序完成。

用户态作用与实现

UIO 用户态的作用
  1. 设备访问:通过 /dev/uioX 文件与设备交互。
  2. 内存映射:使用 mmap 将设备内存映射到用户空间,直接操作设备寄存器。
  3. 中断处理:通过 read 调用等待中断事件。
用户态的实现步骤
  1. 打开设备文件

    int fd = open("/dev/uio0", O_RDWR);
    if (fd < 0) {perror("Failed to open /dev/uio0");return -1;
    }
    
  2. 内存映射
    使用 mmap 将设备内存映射到用户空间:

    void *reg_base = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (reg_base == MAP_FAILED) {perror("Failed to mmap");close(fd);return -1;
    }
    
  3. 处理中断
    通过 read 等待中断事件:

    unsigned int irq_count;
    while (1) {read(fd, &irq_count, sizeof(irq_count));printf("Interrupt received! Count: %d\n", irq_count);
    }
    
  4. 释放资源
    在程序结束时,释放映射的内存并关闭设备:

    munmap(reg_base, 0x1000);
    close(fd);
    

示例代码

内核态代码

以下是一个完整的内核态代码示例:

#include <linux/module.h>
#include <linux/uio_driver.h>static irqreturn_t my_irq_handler(int irq, struct uio_info *dev_info) {return IRQ_HANDLED;
}static struct uio_info my_uio_info = {.name = "my_device",.version = "1.0",.irq = 42,.irq_flags = IRQF_SHARED,.handler = my_irq_handler,.mem[0].addr = 0x40000000,.mem[0].size = 0x1000,.mem[0].memtype = UIO_MEM_PHYS,
};static int __init my_uio_init(void) {return uio_register_device(NULL, &my_uio_info);
}static void __exit my_uio_exit(void) {uio_unregister_device(&my_uio_info);
}module_init(my_uio_init);
module_exit(my_uio_exit);
MODULE_LICENSE("GPL");
用户态代码

以下是对应的用户态代码示例:

#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>int main() {int fd = open("/dev/uio0", O_RDWR);if (fd < 0) {perror("Failed to open /dev/uio0");return -1;}void *reg_base = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (reg_base == MAP_FAILED) {perror("Failed to mmap");close(fd);return -1;}unsigned int irq_count;while (1) {read(fd, &irq_count, sizeof(irq_count));printf("Interrupt received! Count: %d\n", irq_count);}munmap(reg_base, 0x1000);close(fd);return 0;
}

注意事项

  1. 中断功能
    • 如果不需要中断功能,可以省略中断处理函数,并将 irq 设置为 UIO_IRQ_NONE
  2. 性能问题
    • 使用 UIO 时,中断和用户空间之间的切换会增加延迟,不适合高实时性场景。
  3. 安全性
    • UIO 将设备的硬件资源直接映射到用户空间,需确保用户空间程序的安全性,以防止资源滥用。

总结

UIO 是一种简化设备驱动开发的高效工具,适合处理简单设备或快速原型开发。在内核态中,开发者只需完成资源注册和中断处理(可选);在用户态中,程序通过 /dev/uioX 文件与设备交互,完成具体逻辑。


http://www.ppmy.cn/devtools/145912.html

相关文章

内网穿透ubuntu20 docker coplar

sudo apt-get install curl curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bash ubuntu-base报错 /sbin/init:No such file or directory解决办法 apt install systemd 命令安装即可 cpolar version 1.3 token认证 登录cpolar官网后台…

《信管通低代码信息管理系统开发平台》Windows环境安装说明

1 简介 《信管通低代码信息管理系统应用平台》提供多环境软件产品开发服务&#xff0c;包括单机、局域网和互联网。我们专注于适用国产硬件和操作系统应用软件开发应用。为事业单位和企业提供行业软件定制开发&#xff0c;满足其独特需求。无论是简单的应用还是复杂的系统&…

数据可视化期末复习-简答题

数据可视化的标准 实用性 完整性 真实性 艺术性 交互性 数据可视化的目标 通过数据可视化有效呈现数据中的重要特征 通过数据可视化揭示事物内部的规律和数据之间的内在联系 通过数据可视化辅助人们理解事物的概念和过程 通过数据可视化对模拟和测量进行质量监控 通…

音视频入门知识(四):封装篇

⭐四、封装篇 H264封装成mp4、flv等格式&#xff0c;那为什么需要封装&#xff1f; ​ h264也能播放&#xff0c;但是按照帧率进行播放&#xff0c;可能不准 ★FLV **FLV&#xff08;Flash Video&#xff09;**是一种用于传输和播放视频的容器文件格式。FLV 格式广泛应用于流媒…

第1章 R语言中的并行处理入门

标准&#xff1a;时间,开发&#xff0c;运行,工具&#xff0c;R机器&#xff0c;多核。 rdsm,openmp,conda。 相互网页外链。 第一章 1.1 反复出现的主题: 良好并行所具有的标准 R(解释性语言)的核心操作都在语言内部进行了高效的实现&#xff0c;因而只要正确使用&#xff…

2024年12月一区SCI-加权平均优化算法Weighted average algorithm-附Matlab免费代码

引言 本期介绍了一种基于加权平均位置概念的元启发式优化算法&#xff0c;称为加权平均优化算法Weighted average algorithm&#xff0c;WAA。该成果于2024年12月最新发表在中JCR1区、 中科院1区 SCI期刊 Knowledge-Based Systems。 在WAA算法中&#xff0c;加权平均位置代表当…

【Leetcode】3218. 切蛋糕的最小总开销 I

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 有一个 m ∗ n m * n m∗n 大小的矩形蛋糕&#xff0c;需要切成 1 ∗ 1 1 * 1 1∗1 的小块。 给你整数 m m m &#xff0c; n n n 和两个数组&#xff1a; h o r i z o n t a l…

java中list和map区别

在Java中&#xff0c;List和Map是两种不同类型的集合接口&#xff0c;它们用于不同的场景并且具有不同的特性和用途。以下是List和Map的主要区别&#xff1a; 1. 数据结构 List&#xff1a;是一个有序的集合&#xff0c;允许重复元素。它实现了Collection接口&#xff0c;并且…