问题描述

昨天同事反馈说 centos 标准内核 release 的 lib/modules 目录中没有生成 modules.dep 文件,这样导致没办法使用 modprobe 来在加载模块时自动处理依赖关系。

是没有生成还是没有提交?

这个问题表面看上去应该挺好搞的,二分法用在这里就是先要判断是没有生成还是没有提交。

重新用 rpmbuild 编译 centos 内核后发现确实没有生成 modules.dep 文件,解包生成的 rpm 文件发现也没有这个问题,看来应该是没有生成。

为此我在 debian 10 的 linux-4.19.98 内核源码上进行测试。

modules.dep 是怎样生成的?

其实我压根不清楚 modules.dep 这个文件是在编译内核的哪一个步骤生成的,网上搜了下说可以调用 depmod 命令来生成,试了下没有搞出来。我一直以为这个 modules.dep 是在编译模块的时候生成的,搞了半天发现它实际是在 modules_install 这一步生成的。

重新使用 depmod 命令生成 modules.dep 文件

在执行 INSTALL_MOD_PATH=./install make modules_install 安装内核模块到 install 目录中时,拷贝完模块后会调用 depmod 生成 modules.dep 等文件。

在安装完成后执行如下命令来生成 modules.dep 等文件。

/sbin/depmod -b ./install 4.19.118

使用脚本生成 modules.dep 文件

其实 modules.dep 文件很容易生成,在每个 ko 文件的 modinfo section 中已经记录了依赖的模块,只需要将这个 section 抽出来,然后格式化输出就能够生成 modules.dep 文件。

我使用如下脚本来生成 modules.dep 文件。

#!/bin/bashif [ -n "$1" ]
thencd $1
elseecho "Please input an pathname like: $0 /lib/modules/4.19.98" > /dev/stderrexit 1
fikolist=$(find . -name '*.ko'  -printf %P"\n" | sort )for one_module in $kolist
dodepends=$(/sbin/modinfo -F depends $one_module)output="$one_module:"  IFS=","for i in $depends;doone_line=" $(find . -name "${i}.ko" -printf "%P")"output=$output$one_linedoneecho $output
done

这个脚本的核心在于使用 modinfo 提取模块中的 depends 信息,然后查找依赖模块的路径并以 modules.dep 的格式输出。

Makefile 中的相关内容

# Target to install modules
PHONY += modules_install
modules_install: _modinst_ _modinst_postPHONY += _modinst_
_modinst_:@rm -rf $(MODLIB)/kernel@rm -f $(MODLIB)/source@mkdir -p $(MODLIB)/kernel@ln -s $(abspath $(srctree)) $(MODLIB)/source@if [ ! $(objtree) -ef  $(MODLIB)/build ]; then \rm -f $(MODLIB)/build ; \ln -s $(CURDIR) $(MODLIB)/build ; \fi@cp -f $(objtree)/modules.order $(MODLIB)/@cp -f $(objtree)/modules.builtin $(MODLIB)/$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst# This depmod is only for convenience to give the initial
# boot a modules.dep even before / is mounted read-write.  However the
# boot script depmod is the master version.
PHONY += _modinst_post_modinst_post: _modinst_$(call cmd,cmd_depmod)

上述 Makefile 脚本中,modules_install 目标依赖_modinst__modinst_post_modinst_post调用 depmod生成 modules.dep等文件。

这里 $(call cmd,cmd_depmod) 中的 cmd 是一个函数,cmd_depmod 是传递给这个函数的参数。

cmd_depmod 标号的定义内容如下:

# Run depmod only if we have System.map and depmod is executable
quiet_cmd_depmod = DEPMOD  $(KERNELRELEASE)                                                                                                                                  cmd_depmod = $(CONFIG_SHELL) $(srctree)/scripts/depmod.sh $(DEPMOD) \$(KERNELRELEASE)

对于 cmd 函数来说,当指定了 quiet 选项后,它使用 quiet_cmd_depmod 命令执行,未指定 quiet 选项则使用 cmd_dpemod 命令执行。

cmd 函数在 scripts/Kbuild.include 中定义,内容如下:

# echo command.
# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
echo-cmd = $(if $($(quiet)cmd_$(1)),\echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)# printing commands
cmd = @$(echo-cmd) $(cmd_$(1))

这个语法相当复杂,我也没有完全搞懂,暂且不进行解释了。

为什么 rpmbuild 没有生成 modules.dep 等文件?

centos 标准内核使用 rpmbuild 生成内核,通过查看编译步骤,发现其中有执行 modules_install 的操作,但没有生成 modules.dep 等相关的文件。

cnetos 标准内核 3.10 中顶层 Makefile 中 _modinst_post 目标的内容如下:

# This depmod is only for convenience to give the initial
# boot a modules.dep even before / is mounted read-write.  However the
# boot script depmod is the master version.
PHONY += _modinst_post
_modinst_post: _modinst_$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst$(call cmd,depmod)

与 debian10 的 4.19.98 内核源码对比,发现 centos 的内核多了编译对 __fw_modinst 的编译行。

kernel.spec 中的相关内容如下:

    if [ "$Flavour" != "kdump" ]; then# Override $(mod-fw) because we don't want it to install any firmware# we'll get it from the linux-firmware package and we don't want conflictsmake -s %{?cross_opts} ARCH=$Arch INSTALL_MOD_PATH=$RPM_BUILD_ROOT modules_install KERNELRELEASE=$KernelVer mod-fw=
%if %{with_gcov}

这里在执行 modules_install 的时候指定了 mod-fw 为空,这就导致 depmod 没有被调用,modules.dep 等文件生成失败。

了解到这点后,我在编译流程中添加调用 depmod 的操作生成 modules.dep 这些文件解决了这个问题。

modprobe 加载内核模块使用的哪些文件呢?

使用 strace 追踪 modprobe 的调用过程,发现 modprobe 并不会使用 modules.dep 文件。

strace 的相关信息记录如下:

[longyu@debian-10:07:30:49] ~ $ strace /sbin/modprobe tun  2>&1 | grep open
............
openat(AT_FDCWD, "/etc/modprobe.d", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
openat(AT_FDCWD, "/lib/modprobe.d", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
openat(AT_FDCWD, "/lib/modprobe.d/aliases.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/modprobe.d/blacklist-nouveau.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modprobe.d/fbdev-blacklist.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modules/4.19.98/modules.softdep", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/modprobe.d/nouveau-kms.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/modprobe.d/qemu-blacklist.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modprobe.d/systemd.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/proc/cmdline", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modules/4.19.98/modules.dep.bin", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modules/4.19.98/modules.alias.bin", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modules/4.19.98/modules.symbols.bin", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modules/4.19.98/modules.builtin.bin", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/sys/module/tun/initstate", O_RDONLY|O_CLOEXEC) = 3

可以看到它访问了 modules.dep.bin、modules.alias.bin、modules.symbols.bin、modules.builtin.bin 等文件,它并没有访问 modules.dep 文件。

man modules.dep 得到了如下证据:

DESCRIPTIONmodules.dep.bin is a binary file generated by depmod listing the dependencies for every module in the directories under /lib/modules/version. It is used by kmodtools such as modprobe and libkmod.Its text counterpar is located in the same directory with the name modules.dep. The text version is maintained only for easy of reading by humans and is in noway used by any kmod tool.

上述信息表明,modules.dep 只是供我们查看的,kmod 相关的命令使用的是 modules.dep.bin 这个文件。

总结

在这个问题里,我的目标是生成 modules.dep 文件,实际上这个文件只是方便用户来查看,并不会被 modprobe 所使用,这表明我在确定问题是什么这里有疏忽,偏离了正确的方向。

正确的流程应该是确认 modprobe 加载模块到底依赖哪些文件,然后再进行处理。

depmod 生成 modules.dep相关推荐

  1. modprobe:FATAL: could not load /lib/modules/2.6.35-22-generic/modules.dep No such file or directory

    给ubuntu升级到10.10 ,开机可能出现错误 modprobe:FATAL: could not load /lib/modules/2.6.35-22-generic/modules.dep ...

  2. Linux 编译内核

    编译内核步骤: 1. 先查看自己OS使用的内核版本 mrzhang@mrzhang:~$ uname -r 4.4.0-51-generic mrzhang@mrzhang:~$ 2. 如果安装系统时 ...

  3. 内核模块相关命令:lsmod,depmod,modprob,modinfo,insmod,rmmod

    lsmod 功能:列出内核已载入模块的状态 用法:lsmod 描述: lsmod 以美观的方式列出/proc/modules的内容. 输出为: Module(模块名)    Size(模块大小)    ...

  4. 内核模块相关命令:lsmod,depmod,modprob...

    lsmod 功能:列出内核已载入模块的状态 用法:lsmod 描述: lsmod 以美观的方式列出/proc/modules的内容. 输出为: Module(模块名)    Size(模块大小)    ...

  5. linux模块创建proc,[Linux 运维]/proc/modules 以及内核模块工具

    [Linux 运维] /proc/modules 以及内核模块工具 1. 基本情况 这个文件列出了所有load进入内核的模块列表.里面的内容会随着系统使用和配置的变化而变化.这里面的很多信息可以通过l ...

  6. 【linux】内核模块管理:lsmod、insmod、rmmod、modinfo、modprobe、depmod命令

    目录 即看即用 一.基本介绍 二.命令介绍 三.命令参数和选项 即看即用 lsmod 查看内核已加载的模块 lsmod lsmod|grep ext4modinfo 查看模块的基本信息 modinfo ...

  7. 系统启动流程 - 理解modules加载流程

    linux 启动流程 module加载 1.启动过程分为三个部分 BIOS 上电自检(POST) 引导装载程序 (GRUB2) 内核初始化 启动 systemd,其是所有进程之父. 1.1.BIOS ...

  8. linux内核模块相关命令:lsmod,depmod,modprobe,modinfo,insmod,rmmod 使用说明

    原文链接:http://www.cnblogs.com/jacklikedogs/p/4659249.html inux内核模块相关命令:lsmod,depmod,modprobe,modinfo,i ...

  9. linux驱动模块命令大全insmod/rmmod/modprobe/depmod/lsmod

    玩过linux程序开发的人都知道,当一个驱动程序以模块化的模式编译之后,它并不是随着系统启动而直接活跃的,而是静静的躺在内核的某个角落里,此时是不可用的.应用程序想要调用该驱动,则必须先加载,然后才能 ...

  10. 简单实例讲解linux的module模块编译步骤

    简单实例讲解linux的module模块编译步骤 (2014-10-24 10:19:17) 标签: module linux 分类:Linux/Unix 本文将直接了当的带你进入linux的模块编译 ...

最新文章

  1. 用户体验已成过去时 AI要从公民乃至社会的角度去思考问题
  2. SCOPE_IDENTITY()
  3. 2018第三季度总结
  4. 关于HtmlParser中Parser【org.htmlparser.Parser】这个类奇怪的地方...求解释【已获得解释】...
  5. redis - 基础
  6. oracle分区大批量update,Oracle 对分区作调整记得加update global indexes
  7. DataWorks OpenAPI企业开发实战-运维监控大屏
  8. Jmeter中JDBC链接配置 JDBC Connection Configuration
  9. webpack的build的时候时间长处理方案
  10. c++ 转bcd码_8421BCD码转换为十进制
  11. stm32寄存器版学习笔记04 定时计数器中断
  12. linux 跟踪程序读写,Linux中pthread行为的跟踪和可视化工具
  13. 蒙文字体怎么安装_蒙文搜索APP内置键盘布局图
  14. SolidWorks基础操作笔记
  15. 安全邮箱怎么注册?邮箱地址是什么?怎么写?快速了解tomvip邮箱
  16. Ubuntu18.04 上 安装微信(Deepin-Wechat)
  17. 关于同构关系的一些证明(1)
  18. lol8月21号服务器维护,8月21日lol维护公告最新 8.21lol维护到几点
  19. Pandas入门超详细教程,看了超简单
  20. 视频教程-Kali Linux渗透测试全程课与脚本语言编程系列课程-渗透测试

热门文章

  1. 高仿微信表情控件 -- LQREmojiLibrary
  2. python设置编码格式为utf-8_python设置文件编码格式为UTF-8
  3. 专题:固体力学中应力与应变分析详解(5.主方向与主应力)
  4. 计算机E盘加密软件,u盘加密软件有哪些?电脑文件夹加密软件哪个好?
  5. 好用的换ip工具分享
  6. 域名是如何变成IP的
  7. postman并发测试_三种高并发测试工具总结(Postman,Apache Bench,Jmeter)
  8. Linux 并发测试工具 httpd-tools工具的安装和使用
  9. 开发者服务器怎么发送公众号上的消息,微信公众号发送提醒消息
  10. pyserial库是python语言用于,python的pyserial模块