凡亿教育-迪丽热巴
凡事用心,一起进步
打开APP
公司名片
凡亿课堂 | 面试指南
当前位置: 首页 面试指南
Linux内核模块怎么写?init/exit函数、insmod/rmmod怎么用?嵌入式Linux面试
浏览量:149
2026-10-06 11:53:07
一句话答案

内核模块是可动态加载的代码,包含 module_init(加载时执行)和 module_exit(卸载时执行);用 Makefile 编译为 .ko,insmod 加载、rmmod 卸载、lsmod 查看、dmesg 看日志;模块运行在内核态,不能用 C 库,用 printk 打印,注意并发和安全。

本文概述

内核模块是 Linux 驱动基础,面试常考:module_init/exit、编译加载、内核态特点。回答要给最小模块代码。

核心要点

  • 内核模块动态加载/卸载,不需要重新编译内核

  • module_init(xxx_init) 加载时调用,module_exit(xxx_exit) 卸载时调用

  • 编译为 .ko,Makefile 用 obj-m += xxx.o,make -C /lib/modules/$(uname -r)/build M=$(pwd) modules

  • insmod xxx.ko 加载,rmmod xxx 卸载,lsmod 查看,dmesg 看 printk 输出

  • 内核态:不能用 C 库(printf/malloc),用 printk/kmalloc,注意并发(锁)和安全(copy_to_user)

终端显示 Linux 内核模块代码,insmod/rmmod/lsmod,dmesg 输出

面试官:写一个最简单的内核模块,加载时打印 Hello,卸载时打印 Bye。

面试官考察点

内核模块基础题。面试官看你是否写过模块。重点听:module_init/exit、编译、加载。

回答思路

给最小模块代码和编译加载命令。

参考回答

最小模块代码(hello.c)。

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

static int __init hello_init(void){
  printk(KERN_INFO "Hello, kernel!\n");
  return 0;
}

static void __exit hello_exit(void){
  printk(KERN_INFO "Bye, kernel!\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Hello module");

Makefile。

obj-m += hello.o
all:
  make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
  make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

编译加载。

make # 编译出 hello.ko
insmod hello.ko # 加载
dmesg | tail # 看到 "Hello, kernel!"
lsmod | grep hello # 查看已加载
rmmod hello # 卸载
dmesg | tail # 看到 "Bye, kernel!"

内核态 vs 用户态。

项目用户态内核态
C 库可用(glibc)不可用
打印printfprintk(带日志级别)
内存分配mallockmalloc/vmalloc
内存访问受保护可访问所有内存
并发多进程/线程中断/软中断/多 CPU,要用锁
崩溃影响进程崩溃内核 panic,系统死机

注意。

  • printk 有日志级别(KERN_EMERG~KERN_DEBUG),dmesg 显示受 console_loglevel 控制;

  • 模块参数用 module_param(name, type, perm),加载时 insmod hello.ko name=value;

  • 导出符号用 EXPORT_SYMBOL(func),其他模块可以调用;

  • 卸载时必须释放所有资源(内存、中断、设备),否则泄漏;

  • 内核模块必须和内核版本一致(vermagic),否则加载失败。

面试官可能追问

追问 1:insmod 和 modprobe 区别?
insmod 直接加载指定 .ko,不解决依赖;modprobe 自动加载依赖模块(从 /lib/modules 查找)。一般用 modprobe。
追问 2:printk 为什么不立即显示?
printk 写到内核环形缓冲区,dmesg 读取。控制台显示受日志级别控制,用 dmesg 或调整 /proc/sys/kernel/printk。
追问 3:模块加载失败常见原因?
版本不匹配(vermagic)、缺少依赖符号、权限不够(要 root)、硬件不存在。用 dmesg 看错误。
追问 4:__init 和 __exit 宏作用?
__init 标记初始化函数,加载后释放内存(内置驱动);__exit 标记卸载函数,内置驱动时不编译。模块驱动时一般不影响。
追问 5:内核模块能调用用户态函数吗?
不能直接调用。可以用 call_usermodehelper 调用用户态程序,或通过 netlink/proc 等和用户态通信。

常见失分表达

✗ 内核模块用 printf/malloc — 内核态没有 C 库,编译失败。
✗ 卸载不释放资源 — 内存/中断泄漏,再次加载出问题。
✗ 不考虑并发 — 多 CPU/中断同时访问导致竞态,数据损坏。

准备动作

1
写过一个最简单的内核模块
2
了解 insmod/rmmod/dmesg
3
准备一个内核模块 panic 最终定位是空指针的案例

核心关键词

内核模块module_initmodule_exitinsmodrmmodprintkko


声明:本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。仅供学习交流使用,不构成商业目的。版权归原作者所有,如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时删除。 侵权投诉

相关文章

辐射骚扰超标时,你为什么先检查线缆和共模电流,而不是直接加屏蔽罩?

2026-10-31 15:42:33

接口滤波器件在PCB上怎么布局?EMC面试要从干扰耦合路径讲起

2026-08-02 21:44:52

PCB拼板怎么设计?V-cut、邮票孔、拼板间距怎么选?PCB面试

2026-10-10 23:08:46

面试被追问不熟悉的芯片或技术,怎么回答才显得靠谱?

2026-10-22 15:51:11

emc设计工程师怎么做?emc设计工程师常见问题及回答技巧

2023-11-27 11:44:26