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

Linux 如何只重新编译单个内核模块?,linux,makefile,linux-kernel,gnu-make,kernel-module,Linux,Makefile,Linux Kernel,Gnu Make,Kernel Module,通常内核源代码存储在/usr/src/linux-2.6.x/中。 要避免在修改模块的源代码时重新编译整个内核,如何仅重新编译该模块?切换到源代码树的根目录并运行以下命令: $ make modules SUBDIRS=drivers/the_module_directory 以及安装已编译的模块: $ make modules_install SUBDIRS=drivers/the_module_directory 注意:正如lunakid所提到的,后一个命令可能不会首先构建模块,因此请小

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

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

$ make modules SUBDIRS=drivers/the_module_directory
以及安装已编译的模块:

$ make modules_install SUBDIRS=drivers/the_module_directory

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

您可以将模块名或模块目录的路径传递给模块,使其成为参数

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

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

  • make distclean
    如果您以前没有克隆新的源代码,而是用于构建其他模块
  • 在某处为模块源创建新文件夹(例如:extra) 并且只将与需要构建的模块相关的源文件(从内核源或其他地方)复制到这个新文件夹中
  • /boot/config-`uname-r`
    文件(例如:/boot/config-4.8.0-46-generic)复制到内核源文件夹文件.config中,然后运行
    make oldconfig
    。如果模块属于内核源,请通过调用
    make menuconfig
    、搜索模块并在必要时应用字母“M”来验证是否已启用该模块
  • 内核源根Makefile必须使用与当前运行的组件匹配的精确版本组件进行更改(您可以使用
    makekernelversion
    验证它是否与
    uname-r
    组件完全匹配)
  • 有一个强烈的建议是,在使用之前也要构建脚本
    制作脚本
  • make prepare
    make modules\u prepare
    必须在实际模块构建之前执行
  • Module.symvers必须从运行内核版本对应的目标系统标题文件夹
    /usr/src/linux headers-`uname-r`/Module.symvers
    (示例:/usr/src/linux-headers-3.13.0-117-generic/Module.symvers)进入为模块编译准备的新创建的模块源文件文件夹(示例中的extra
  • 在模块源代码编译文件夹中创建新的Makefile,该文件夹有以下行:
    obj-y+=.o
    或者如果源代码复杂,请使用
  • 只有这样,才是使用
    make-cm=the_module\u目录构建模块的正确时机(例如:
    make-C.M=extra/
  • 使用命令
    modprobe--dump modversion.ko
    验证导出API的模块与module.symvers中相应值之间的CRC匹配。如果出现故障,请使用命令
    modinfo.ko
  • 验证kernel.release文件内容是否与当前运行版本的标题中的内容完全匹配。如果您在末尾发现附加了+,这意味着您一直在编译git clonned源代码,并且您的实验性修改导致构建系统通过在末尾添加+来破坏localversion字符串
  • 如果只在+内核的尾部发现了release存储值,并且它与目标运行内核的确切名称不匹配
  • 解决办法如下:

    提交所有更改,使用
    git-tag-a-f
    命令强制release标记在修改上方移动。然后从步骤8重建模块

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

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

    构建模块。

    make scripts prepare modules_prepare
    make -C . M=drivers/net/ethernet/intel/e1000
    
    cp drivers/net/ethernet/intel/e1000/e1000.ko /lib/modules/5.1.15/kernel/drivers/net/ethernet/intel/e1000/e1000.ko
    
    安装模块。

    make scripts prepare modules_prepare
    make -C . M=drivers/net/ethernet/intel/e1000
    
    cp drivers/net/ethernet/intel/e1000/e1000.ko /lib/modules/5.1.15/kernel/drivers/net/ethernet/intel/e1000/e1000.ko
    

    (只需确保你在树根上运行,不像我。;@lunakid Good point;)虽然应该很清楚,SUBDIRS与CWD是相对的:PIt是绝对清楚的,但最后我还是发现自己坐在wacom驱动程序目录中。:)只是没有注意我的脚步。另外,请您在回答中补充一下,它也可以以同样的方式安装,只需将
    makemodules\u install SUBDIRS=…
    。这几乎可以肯定是下一步,而且可能不会立即变得微不足道(尽管看起来是这样,例如,我花了几分钟在谷歌上徒劳地搜索了一下……:)。谢谢,干杯@这孩子完了。我假设modules_install也会构建,所以它实际上是一个一步过程+1,thx。至于build+install:似乎不是:不幸的是它本身就是垃圾,如果这确实是它的感觉:install drivers/input/touchscreen/wacom_w8001.ko cp:cannot stat'drivers/input/touchscreen/wacom_w8001.ko':没有这样的文件或目录DEPMOD 3.4.34-x61t`(尽管仍然运行DEPMOD,这就是我不确定的原因)make path/to/the/module/other.ko比make modules SUBDIRS=directory/path花费更多的时间(3分钟vs 5秒)。实际上,make path/to/directory似乎不起作用,它总是说“什么都不做”,但我确实修改了代码如果驱动程序有自己的子目录(例如linux/drivers/net/ethernet/natsemi),是否仍然需要将驱动程序代码复制到自己的“额外”文件夹中?