如何将FUSE内核模块编译选项从y改为m且避免启动失败?
一、修复启动挂起问题
启动挂起的核心原因是根文件系统或启动依赖服务需要FUSE模块,但模块未提前加载就被调用,Ubuntu 20.04默认环境中可能存在snap、AppArmor组件或挂载工具依赖FUSE。可按以下步骤处理:
将FUSE模块加入initramfs
编辑/etc/initramfs-tools/modules文件,添加一行:fuse
重新生成对应内核的initramfs:update-initramfs -u -k <你的新内核版本号>
这样系统启动初期就会加载FUSE模块,避免依赖缺失导致挂起。排查启动依赖进程
用正常启动的旧内核查看新内核的启动日志:journalctl --boot=-1(-1代表上一次启动),定位挂起时的阻塞进程。
如果是snap相关服务依赖FUSE,可临时禁用snap自动启动,待模块加载后再手动启动,或调整服务启动顺序为延迟启动。单用户模式验证
在GRUB启动项中添加init=/bin/bash进入单用户模式,手动执行insmod /path/to/fuse.ko后,再执行systemctl start multi-user.target,验证是否能正常启动,以此确认是否为FUSE模块加载时机的问题。
二、便捷的FUSE内核模块调试替代方法
若修改CONFIG_FUSE_FS为m的流程过于繁琐,可尝试以下调试方案:
单独编译FUSE模块
无需编译整个内核,仅针对FUSE模块编译:- 进入内核源码目录,确保当前
.config文件中CONFIG_FUSE_FS=m - 执行编译命令:
make M=fs/fuse - 完成后直接用
rmmod fuse && insmod fs/fuse/fuse.ko替换原有模块,节省编译时间。
- 进入内核源码目录,确保当前
Out-of-Tree模块编译
复制FUSE模块源码到独立目录,编写简易Makefile:obj-m += fuse.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: $(MAKE) -C $(KDIR) M=$(PWD) clean执行
make即可基于当前内核头文件编译FUSE模块,适合快速迭代修改调试,前提是原有FUSE已设为模块(m)。动态追踪调试
无需修改模块源码,利用内核ftrace或kprobes追踪逻辑:- 追踪FUSE函数调用:
echo 'p:myprobe fuse_do_open' > /sys/kernel/debug/tracing/kprobe_events - 查看追踪日志:
cat /sys/kernel/debug/tracing/trace - 这种方式适合快速定位问题点,无需重新编译加载模块。
- 追踪FUSE函数调用:
QEMU虚拟机调试
搭建极简虚拟机环境,编译带调试信息的内核(开启CONFIG_DEBUG_INFO=y和CONFIG_GDB_SCRIPTS=y),启动QEMU时添加-s -S参数,通过GDB远程连接target remote :1234加载模块符号,实现单步调试。
内容的提问来源于stack exchange,提问作者Emily Green

