dmesg日志中的错误代码(如-2、-22)才是定位模块加载失败根源的关键,而非insmod/modprobe的通用退出码;-2对应ENOENT(文件缺失)、-22对应EINVAL(ABI不匹配)、-1多因Unknown symbol(依赖未加载),需结合dmesg上下文精准识别。

直接看 dmesg 输出,错误代码(如 -1、-22)就藏在最后一行或模块加载附近几行里,不是 insmod 或 modprobe 的返回值本身。
为什么不能只信命令退出码
像 insmod ./xxx.ko 返回 -1,这个 -1 是通用失败码,不指代具体原因;真正带上下文的错误代码(比如 -ENOENT、-EINVAL、-EPERM)只出现在内核日志中,且通常以数字形式(-2、-22)紧贴错误描述出现。
常见对应关系:
-
-2→ENOENT:模块文件不存在或路径错 -
-22→EINVAL:模块格式无效,比如内核版本/ABI 不匹配 -
-1→ 多数是Unknown symbol类问题,但需结合上下文确认 -
-13→EACCES:权限不足或模块被标记为 tainted(如含非 GPL 符号)
快速定位错误代码的三步操作
执行完 insmod 或 modprobe 后立刻运行:
dmesg | tail -n 20
重点关注最后 3–5 行,尤其是包含模块名和 “error”、“failed”、“Unknown symbol” 的那行——错误代码就在它旁边或下一行。
例如:
insmod: error inserting './igb.ko': -1 [ 1234.567890] igb: Unknown symbol dca_add_requester (err -2)
这里真正的错误代码是 -2,说明符号 dca_add_requester 找不到(依赖模块未加载),不是模块文件丢失。
实操建议:
- 用
dmesg -T加本地时间戳,避免日志滚动太快错过关键行 - 如果日志刷屏快,先
dmesg -c清空缓冲区,再跑insmod,然后dmesg直接看新输出 - 不要依赖
modprobe --verbose—— 它不打印内核级错误码,只显示加载步骤
错误代码和 modinfo、readelf 的联动判断
看到 -22(EINVAL)时,大概率是模块与当前内核 ABI 不兼容,这时要立刻交叉验证:
- 运行
modinfo ./xxx.ko | grep vermagic,比对uname -r输出 - 运行
readelf -h ./xxx.ko,检查Machine(架构)和OS/ABI字段是否匹配当前系统 - 若
vermagic中含modversions,而当前内核没开启CONFIG_MODVERSIONS,就会报-22
注意:-22 不一定等于“编译错了”,也可能是内核配置开关不一致,比如 CONFIG_NETFILTER 关闭导致 nf_conntrack 相关模块加载失败。
systemd 场景下怎么抓错误代码
如果是开机时模块加载失败(比如 systemctl status systemd-modules-load.service 显示 failed),错误代码不会出现在 service 日志里,必须查内核日志:
journalctl -k | grep -A 3 -B 1 "Failed to load.*\.ko"
或者更直接:
journalctl -k -n 50 | grep -E "(Unknown symbol|Invalid module format|Operation not permitted)"
systemd 本身不解析或暴露内核返回的具体错误码,它只记录“module loading failed”,根源仍在 dmesg 缓冲区。
容易忽略的一点:某些发行版(如 RHEL/CentOS)会把早期内核日志刷到 /var/log/messages,但错误代码仍以原始数字形式存在,搜索 err -\d+ 比搜文字更可靠。



















