如何以modules的方式编译驱动

发布时间:2022-01-12 15:22:00 作者:iii
来源:亿速云 阅读:144
# 如何以modules的方式编译驱动

## 1. Linux驱动模块概述

Linux内核驱动可以两种方式集成到系统中:
- **静态编译**:直接编译进内核镜像(zImage/bzImage)
- **动态加载**:编译为可加载模块(.ko文件)

模块化驱动的优势:
- 无需重新编译整个内核
- 运行时动态加载/卸载
- 节省内存(不使用时可不加载)
- 方便调试和开发

## 2. 开发环境准备

### 2.1 内核头文件安装
```bash
# Ubuntu/Debian
sudo apt install linux-headers-$(uname -r)

# RHEL/CentOS
sudo yum install kernel-devel

2.2 验证头文件路径

确保/lib/modules/$(uname -r)/build指向正确内核源码

3. 最简单的模块示例

3.1 示例代码 hello.c

#include <linux/module.h>
#include <linux/init.h>

static int __init hello_init(void)
{
    printk(KERN_INFO "Hello module loaded\n");
    return 0;
}

static void __exit hello_exit(void)
{
    printk(KERN_INFO "Hello module unloaded\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Simple hello world module");

3.2 对应的Makefile

obj-m := hello.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

all:
	make -C $(KDIR) M=$(PWD) modules

clean:
	make -C $(KDIR) M=$(PWD) clean

4. 模块编译详解

4.1 关键编译命令

make -C /lib/modules/$(uname -r)/build M=$(pwd) modules

参数说明: - -C:指定内核源码目录 - M=:指定模块源码目录 - modules:编译目标

4.2 生成的文件

5. 模块操作实践

5.1 加载模块

sudo insmod hello.ko
# 查看输出
dmesg | tail

5.2 查看模块信息

# 列出已加载模块
lsmod | grep hello

# 查看模块信息
modinfo hello.ko

5.3 卸载模块

sudo rmmod hello
# 验证卸载
dmesg | tail

6. 多文件模块编译

6.1 多文件模块示例

主文件main.c:

#include "module.h"

static int __init main_init(void) {
    module_func();
    return 0;
}
...

module.h/module.c实现辅助功能

6.2 对应Makefile修改

obj-m := complexmod.o
complexmod-objs := main.o module.o

7. 模块参数传递

7.1 带参数的模块示例

static int debug_level = 0;
module_param(debug_level, int, 0644);
MODULE_PARM_DESC(debug_level, "Debug level (0-3)");

7.2 加载时传参

sudo insmod param_mod.ko debug_level=2

8. 模块签名与安全

8.1 生成签名密钥

openssl req -new -x509 -newkey rsa:2048 -keyout key.priv -outform DER -out key.x509 -nodes -days 36500 -subj "/CN=My Module Key/"

8.2 编译带签名模块

修改Makefile:

CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_ALL=y

9. 调试技巧

9.1 打印调试

printk(KERN_DEBUG "Debug message: %d\n", var);

9.2 使用GDB调试

gdb vmlinux /proc/kcore

10. 常见问题解决

10.1 版本不匹配错误

version magic '5.4.0-xx SMP mod_unload ' should be '5.4.0-yy...'

解决方案: - 使用匹配的内核头文件 - 关闭CONFIG_MODVERSIONS

10.2 符号未找到

Unknown symbol in module

解决方案: - EXPORT_SYMBOL导出所需符号 - 检查模块依赖关系

结语

模块化驱动开发是Linux驱动工程师的核心技能。通过本文介绍的方法,您可以: 1. 快速构建可加载模块 2. 实现多文件复杂驱动 3. 进行模块调试和参数配置 4. 解决常见编译问题

建议进一步学习: - Linux设备模型 - 字符设备驱动开发 - 设备树(Device Tree)使用 “`

注:本文实际约1200字,可根据需要删减示例代码部分调整字数。完整开发建议准备: 1. 稳定的Linux开发环境 2. 内核源码树 3. 版本控制工具(git) 4. 调试工具集(printk, gdb等)

推荐阅读:
  1. 如何以Nginx脚本方式切割日志
  2. 编译之驱动程序的编译

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

modules

上一篇:apt-get命令的使用方法有哪些

下一篇:域名如何进行绑定解析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》