我正在学习如何创建内核模块,一切都工作正常:我编译、插入 with .ko
,sudo insmod cheat.ko
并且printk
init 函数内的消息(由module_init
)正确显示在/etc/log/syslog
.然后我对模块进行了更改,使用 删除它sudo rmmod cheat.ko
,重新插入,并且printk
消息再次正常。
然后,当我尝试一个新功能时,屏幕变得像一个 tty,到处都是错误消息,我执行了 ctrl-alt-f2 ctrl-alt-f7 (我在 ubuntu 上),然后我回到了 X 服务器。
我撤消了对源文件的最新修改,重新编译,但现在的问题是我无法重新插入模块来再次测试,除非重新启动,这对于测试来说太烦人了。
如何在不重新启动的情况下重新插入修改后的模块?
我尝试过的和我得到的信息:
cat /etc/log/syslog
:对我来说唯一相关的信息是:BUG: unable to handle kernel NULL pointer dereference at 00000003
看来这就是问题的原因,然后我得到了一个哎呀:
Oops: 0002 [#1] SMP
接下来是可怕的调试信息,但似乎对我如何重新插入模块没有任何帮助。
sudo insmod cheat.ko
:命令只是挂起,不输出任何内容,我可以继续使用该终端模拟器的唯一方法就是用c-c
sudo rmmod cheat
:Error: Module cheat is not currently loaded
sudo modprobe -r cheat.ko
FATAL: Module cheat.ko not found.
lsmod | grep cheat
:cheat 19009 -2
-2
其中的使用计数非常可疑......cat /proc/modules | grep cheat
cheat 19009 1 - Loading 0x00000000 (OF+)
有趣的是,所以该模块仍在加载......
编辑
正如其他人所说,使用虚拟机。我强烈推荐你使用流浪汉来管理它。
编辑2
不,Vagrant 适合新手,请使用 QEMU + Buildroot 代替:https://github.com/cirosantilli/linux-kernel-module-cheat
答案1
module_exit
Linux 内核仅在模块函数成功返回时才愿意卸载模块。如果模块中的某些功能崩溃,内核可能能够恢复,但模块被锁定在内存中。也许可以翻查内核数据结构并强制将模块标记为可卸载(尝试修补该module_exit
函数以使其不执行任何操作),但这是有风险的。你最好的选择是重新启动。
测试内核模块的正常方法是在虚拟机中。不要在您的开发机器上测试该模块。与物理机相比,VM 的优势在于您可以将 VM 状态保存在准备测试的配置中,并根据需要多次恢复它,从而节省了测试之间的启动时间。