ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

嵌入式 Linux 内核模块是怎么“动态加载”的?

嵌入式 Linux 内核模块是怎么“动态加载”的? 在嵌入式 Linux 开发中,我们经常会看到这样的操作:insmod xxx.ko然后驱动就“进内核了”。表面上看,这只是加载一个.ko文件,但从系统内部来看,这个过程实际上涉及用户空间、系统调用、ELF解析、符号解析、地址重定位、版本校验、权限检查、模块初始化以及依赖管理等多个环节。更重要的是,Linux 的动态模块机制并不只是为了方便开发。对于资源有限、硬件型号众多、需要快速迭代的嵌入式设备而言,模块化本身就是一种系统架构设计。一、为什么嵌入式 Linux 不把所有驱动都编进内核?Linux 中的驱动通常有三种状态:直接编译进内核编译成可动态加载的模块完全不编译对应到内核配置中,通常可以理解为:Y → 编进内核 M → 编译成模块 N → 不启用例如:USB摄像头驱动 ↓ ┌────┴────┐ │ │ Y方式 M方式 │ │ 内核启动时 系统运行后 直接初始化 按需加载对于资源比较紧张的嵌入式设备而言,所有驱动全部采用静态方式并不是最优选择。假设一套产品有多个硬件版本:产品A → 摄像头A 产品B → 摄像头B 产品C → 摄像头C 产品D → 摄像头D如果把所有可能用到的驱动都编译进内核,那么最终得到的内核镜像会越来越庞大。而采用模块化设计之后,可以变成:统一Kernel │ ├── camera_a.ko ├── camera_b.ko ├── camera_c.ko ├── wifi.ko ├── usb_serial.ko └── ...设备根据实际硬件和运行需求加载对应模块。因此,动态模块的核心价值不是“方便加载”,而是把内核从一个庞大的整体拆成可以独立管理的功能单元。二、.ko到底是什么?很多初学者第一次接触 Linux 驱动时,会产生一个疑问:.ko是不是类似Windows里面的动态库?从概念上可以类比,但不能简单等同。.ko是:Kernel Object,内核对象文件。它本质上是一个经过编译、链接后形成的内核模块目标文件,采用 ELF 相关格式组织代码、数据、符号和重定位等信息。例如:hello.c ↓ 编译 ↓ hello.o ↓ 链接/模块构建 ↓ hello.ko一个模块内部通常包含:.text → 代码 .data → 已初始化数据 .bss → 未初始化数据 符号表 → 模块需要/提供的符号 重定位信息 → 运行时地址修正 模块元数据 → license、vermagic等所以:.ko不是一段简单的机器码,而是一个可以被内核解析、重定位和注册的模块化目标文件。三、一个最简单的 Linux 内核模块先从最简单的模块开始。#includelinux/init.h#includelinux/module.hstaticint__inithello_init(void){printk("Hello World!\n");return0;}staticvoid__exithello_exit(void){printk("Goodbye World!\n");}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL"
返回列表