Linux 如何仅重新编译单个内核模块?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8744087/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:56:01  来源:igfitidea点击:

How to recompile just a single kernel module?

linuxmakefilelinux-kernelgnu-makekernel-module

提问by user1056635

Usually kernel source are stored in /usr/src/linux-2.6.x/. To avoid to recompile the entire kernel if I modify a module's source, how can I recompile just that module?

通常内核源代码存储在/usr/src/linux-2.6.x/. 为了避免在修改模块的源代码时重新编译整个内核,我该如何只重新编译该模块?

回答by Niklas B.

Switch to the root directory of your source tree and run the following command:

切换到源代码树的根目录并运行以下命令:

$ make modules SUBDIRS=drivers/the_module_directory

And to install the compiled module:

并安装编译模块:

$ make modules_install SUBDIRS=drivers/the_module_directory

Note:As lunakid mentions, the latter command might notbuild the module first, so be careful.

注意:正如 lunakid 提到的,后一个命令可能不会先构建模块,所以要小心。

回答by Szilárd Pfeiffer

You can pass the path to the module name or module directory to make as parameter.

您可以将路径传递到模块名称或模块目录以作为参数。

make path/to/the/module/itself.ko
make path/to/the/module/directory/

回答by Oleg Kokorin

since kernel versions 3.x.xand 4.x.xthe procedure gets more complicated (but there is a hope, so keep reading):

由于内核版本3.xx4.xx,过程变得更加复杂(但有希望,所以请继续阅读):

  1. make distcleanif you haven't just cloned a new source but used to build other modules before
  2. create new folder somewhere for the module source (example: extra) and copy only source files (from the kernel source or somewhere else) related to the module needed to be build into this new folder
  3. copy /boot/config-`uname -r`file (example: /boot/config-4.8.0-46-generic) into kernel source folder file .configand run make oldconfig. if the module belongs to the kernel source, verify if it has been enabled by calling make menuconfig, by searching for the module and applying letter 'M' if necessary
  4. kernel source root Makefilehas to be altered with exact version components matching the current running one (you may verify with make kernelversionif it matches exactly the uname -rone)
  5. there is been a strong suggestion to build scripts also before with make scripts
  6. make prepareand make modules_preparehas to be executed prior to the actual module build
  7. Module.symvershas to be copied from the target system headers folder corresponding running kernel version /usr/src/linux-headers-`uname -r`/Module.symvers(example: /usr/src/linux-headers-3.13.0-117-generic/Module.symvers) into the newly created module source files folder prepared for the module compilation (the one extrain example).
  8. create new Makefileinside module source compilation folder having following line: obj-y += <module_source_file_name>.oor if the source code is complicated, use the guidance from here
  9. only then it's the right time to build module with make -C <kernel source path> M=the_module_directory(example: make -C . M=extra/)
  10. Use command modprobe --dump-modversion <module_name>.koto verify CRC match between module exporting API and corresponding values in Module.symvers. in case of failure use command modinfo <module_name>.koinstead
  11. verify if kernel.releasefile content match exactly the one from headers of the current running version. if you'll discover +appended at the end, it means you've been compiling git clonned source and your experimental modifications caused build system to compromise the localversion string by adding +at the end.
  12. if only +has been discovered at the tail of kernel.releasestored value and it's a mismatch with the exact name of the target running kernel,
  1. make distclean如果你之前不只是克隆了一个新的源,而是用来构建其他模块
  2. 在某处为模块源(例如:extra)创建新文件夹,并仅将与需要构建的模块相关的源文件(来自内核源或其他地方)复制到此新文件夹中
  3. /boot/config-`uname -r`文件(例如:/boot/config-4.8.0-46-generic)复制到内核​​源文件夹文件.config并运行make oldconfig. 如果模块属于内核源代码,请通过调用make menuconfig、搜索模块并在必要时应用字母“M”来验证它是否已启用
  4. 内核源根Makefile必须使用与当前正在运行的组件匹配的确切版本组件进行更改(您可以验证它make kernelversion是否完全匹配uname -r
  5. 之前也有强烈建议使用以下命令构建脚本 make scripts
  6. make prepare并且make modules_prepare必须在实际模块构建之前执行
  7. Module.symvers必须从目标系统 headers 文件夹中对应运行的内核版本/usr/src/linux-headers-`uname -r`/Module.symvers(例如:/usr/src/linux-headers-3.13.0-117-generic/Module.symvers)复制到新创建的准备好的模块源文件文件夹中用于模块编译(示例中额外的一个)。
  8. 在具有以下行的模块源编译文件夹中创建新的Makefileobj-y += <module_source_file_name>.o或者如果源代码很复杂,请使用此处的指导
  9. 只有它的合适的时间来构建模块make -C <kernel source path> M=the_module_directory(例如:make -C . M=extra/
  10. 使用命令modprobe --dump-modversion <module_name>.ko来验证模块导出 API 和Module.symvers 中相应值之间的 CRC 匹配。在失败的情况下使用命令modinfo <module_name>.ko代替
  11. 验证kernel.release文件内容是否与当前运行版本的头文件内容完全匹配。如果您发现在末尾附加了+,则表示您一直在编译 git 克隆源,并且您的实验性修改导致构建系统通过在末尾添加+来破坏 localversion 字符串。
  12. 如果在kernel.release存储值的尾部只发现+并且它与目标运行内核的确切名称不匹配,

the solution would be following:

解决方案如下:

commit all your changes, force release tag to shift above your modifications with the git tag -a <tag version> -fcommand. then rebuild your modules from step 8

提交所有更改,使用git tag -a <tag version> -f命令强制释放标签移动到您的修改之上。然后从步骤 8 重建模块

回答by rocky

make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install

https://askubuntu.com/questions/515407/how-recipe-to-build-only-one-kernel-module

https://askubuntu.com/questions/515407/how-recipe-to-build-only-one-kernel-module

回答by siz

In case you have edited just code in drivers/net/ethernet/intel/e1000/e1000_main.c file

如果您只编辑了drivers/net/ethernet/intel/e1000/e1000_main.c 文件中的代码

Build the module.

构建模块。

make scripts prepare modules_prepare
make -C . M=drivers/net/ethernet/intel/e1000

Install the module.

安装模块。

cp drivers/net/ethernet/intel/e1000/e1000.ko /lib/modules/5.1.15/kernel/drivers/net/ethernet/intel/e1000/e1000.ko