第9周:内核模块开发入门
目标:能够编写、编译、加载和卸载 Linux 内核模块,理解内核空间与用户空间的交互机制。
1. 内核模块基础
1.1 Hello World 模块
1 | // hello.c |
1.2 编译系统(Kbuild)
1 | # Makefile |
1 | # 编译 |
1.3 模块参数
1 |
|
1 | # 带参数加载 |
1.4 模块依赖
1 | // 声明依赖 |
2. printk 与日志系统
2.1 printk 日志级别
1 | printk(KERN_EMERG "System unusable\n"); // 0,紧急 |
日志级别控制:
1 | # 查看当前控制台日志级别 |
dmesg 过滤:
1 | # 按级别过滤 |
2.2 printk vs printf
| 特性 | printk | printf |
|---|---|---|
| 运行环境 | 内核空间 | 用户空间 |
| 输出目标 | 内核日志缓冲区 | stdout |
| 格式支持 | 受限(无浮点) | 完整 |
| 安全性 | 不能睡眠/阻塞 | 可以 |
| 性能 | 较慢(缓冲区+调度) | 快 |
⚠️ printk 限制:
1 | // ❌ 不能使用浮点(内核无 FPU 上下文) |
3. /proc 文件系统
3.1 创建 /proc 文件
1 | // proc_demo.c |
1 | # 测试 |
3.2 /proc 目录结构
1 | /proc/ |
4. 内核数据结构与内存管理
4.1 常用内核数据结构
1 |
|
4.2 内核内存分配
1 |
|
kmalloc vs vmalloc 对比:
| 特性 | kmalloc | vmalloc |
|---|---|---|
| 物理连续性 | 物理连续 | 仅虚拟连续 |
| 最大大小 | 通常 ≤ 128KB | 几乎无限制 |
| 速度 | 快(DMA 友好) | 慢(TLB 抖动) |
| DMA 使用 | 可直接用 | 需要映射 |
| 适用场景 | 小对象、DMA | 大缓冲区 |
5. 实践:/proc 网络连接统计
1 | // net_counter.c |
1 | # 编译加载 |
6. 内核调试技巧
6.1 常用调试方法
1 | # === 日志 === |
6.2 内核 Oops / Panic 分析
1 | # 内核 Oops 信息解读 |
7. 开发环境搭建
7.1 安装内核头文件
1 | # Ubuntu/Debian |
7.2 内核源码阅读
1 | # 下载源码 |
7.3 cscope / ctags 配置
1 | # 生成标签 |
8. 安全注意事项
1 | // === 必须检查的参数 === |
- 本文作者: CoderSong
- 本文链接: https://jack-song-gif.github.io/2026/07/20/第9周:内核模块开发入门/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!