用可加载模块替换内核内置模块 [英] Replace kernel builtin module with a loadable one

查看:97
本文介绍了用可加载模块替换内核内置模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开发了一个内核模块,用于将nf4标签作为char设备进行管理.

I have developped a kernel module to manage a nf4 tag as a char device.

我已经在内核外部开发了该模块,并在开发阶段对其进行了测试,并将其编译为可加载的内核模块(即.ko).

I have developped this module outside of the kernel and tested it compiled as a loadable kernel module (i.e. .ko) during the development phase.

一旦驱动程序正常运行并足够稳定,我便会使用补丁将其插入Linux内核源代码(v4.9.30),以便将其构建为内核的一部分.

Once the driver has been functional and stable enough I have inserted it into linux kernel source (v4.9.30) using patches so it's built as part of the kernel.

在这种情况下,由于模块是内置的,因此会在启动时由内核对其进行加载探测,并出现在设备树中.

Here I'm in the situation where the module is loaded probed at boot by kernel as it's builtin and it appears into the device tree.

现在,我想对驱动程序进行一些改进,但我不想直接在内核中实现这些更改.

Now, I would like to try some improvements on the driver and I don't want to implement those changes directly into the kernel.

因此,我想将驱动程序的代码集成到linux内核中,但不要在启动时将其插入. 为此,我只是使用status = "disable";将驱动程序的status字段更改为设备树,实际上在启动时不再插入该模块.

So I would like to keep the driver's code integrated into linux kernel but not having it inserted at boot. To do this I have just changed the driver's status field with status = "disable"; into the device-tree and indeed the module is not inserted anymore at boot.

但是,我无法插入已修改的可加载模块.我插入ENODEV,这是由于在探测功能中未找到platform_device所致.

However I can't insert the loadable module which as been modified. I'm having a ENODEV at insertion which is due to the platform_device not beeing found into the probe function.

我不明白的是,为什么除了状态字段值外,没有更改设备树,为什么找不到平台设备.

What I don't understand is why the platform device is not beeing found when the device-tree hasn't been changed except for status field value.

添加有关情况的精确度

Add precisions about the situation

经过更多的探索之后,我不得不精确地说,我什至没有进入回调nf4_probe.

After some more exploring I have to precise that I'm not even entering the callback nf4_probe.

检查platform_driver_probe实施后(请参见 here )进入v4.9.30内核源,似乎错误来自此处:

After checking platform_driver_probe implementation (see here) into v4.9.30 kernel source it seems that the error comes from here:

if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
    retval = -ENODEV;

通过从命令行检查设备树,我可以看到设备已定义为目录/proc/device-tree/nf4tag存在,并且目录中填充了与设备树相对应的值.

By checking the device-tree from the command line I can see that the device is defined as the directory /proc/device-tree/nf4tag exists and is filled with values corresponding to those into the device-tree.

在@sawdust的答案之后添加有关问题目的的精确度

Add precisions about the aim of the question after @sawdust's answer

我显然误会为status=disable意味着该设备在硬件配置上根本不存在.尽管只是描述了是否应该探测驱动程序.

I was apparently misunderstanding that status=disable meant that the device wasn't present at all on the hardware configuration. Though it was just describing weither the driver should be probed or not.

为了更清楚地说明我的目标,我明确指出我已将驱动程序编码为适当的模块,并已编译为我正在使用的内核的可加载模块.

To make my objective clearer I precise that I do have the driver coded as proper module and compiled as a loadable module for the kernel I'm using.

但是,我不想重新编译内核以测试我所做的每个更改.因此,我的目的是仅重新编译.ko,直到进行修改为止,然后,在完成所有操作后,使用补丁将这些修改添加到内置模块中.

However I don't want to recompile the kernel to test every change I do. So my aim is to recompile only the .ko until my modifications are made and then, once everything has been done, add those modifications to the builtin moduleusing a patch.

通过这种工作方式,我可以重建.ko并将其插入到我的目标平台上,而不必为每次修改重新编译内核.

With this way of working I can just rebuild the .ko and insert it on my target platform instead of recompiling a kernel for each modification.

因此,恢复我的问题应该是:

So to resume my question should have been:

如何用可加载模块替换内置模块而无需重新编译内核以禁用内置模块?

除了禁用内置模块编译到内核之外,也许没有其他解决方案.

Maybe there isn't a solution for this aim except disabling builtin module compiling onto kernel.

推荐答案

我不明白的是,为什么除了状态字段值外,没有更改设备树,为什么找不到平台设备.

What I don't understand is why the platform device is not beeing found when the device-tree hasn't been changed except for status field value.

您似乎误解了status = "disable"属性的实际含义.
除了表示内核应该不将其插入引导" 之外,禁用的节点还意味着该设备根本不是 current 硬件配置的一部分.
不管是内置模块还是可加载模块,都不会对其进行探测,因为当前配置已禁用该驱动程序.

You seem to misunderstand what the status = "disable" attribute actually means.
Besides it meaning that the kernel should "not having it inserted at boot", a disabled node means that the device is not part of the current hardware configuration at all.
The driver, whether built-in or loadable module, is simply not to be probed because it has been disabled for the current configuration.

如果希望驱动程序(无论是内置模块还是可装入模块)处于当前配置中,则在其设备树"节点中具有status = "okay"属性.

If you want your driver, whether built-in or loadable module, to be in the current configuration, then have a status = "okay" attribute in its Device Tree node.

IOW设备树用于描述内核的当前硬件配置.
不要尝试使用设备树来控制可加载模块(因为它不能).

IOW the Device Tree is for describing the current hardware configuration to the kernel.
Do not try to use the Device Tree to control loadable modules (since it cannot).

在这种情况下,模块是由内核在引导时加载的,因为它是内置的,并且出现在设备树中.

Here I'm in the situation where the module is loaded at boot by kernel as it's builtin and it appears into the device tree.

该语句没有意义,因为您似乎同时将驱动程序描述为内置模块和可加载模块.
不必加载" 内置驱动程序即可调用其探测例程.
由于驱动程序可以是内置的,也可以是可加载的,因此加载"和探测"是两个不同的阶段,因此不应混为一谈.

This statement makes no sense, as you seem to be describing your driver simultaneously as a built-in module as well as a loadable module.
A built-in driver does not have to be "loaded" in order to invoke its probe routine.
Because a driver can be either built-in or loadable, "loading" and "probing" are two distinct phases, and should not be conflated.

因此,我想将驱动程序的代码集成到linux内核中,但不要在启动时将其插入.

So I would like to keep the driver's code integrated into linux kernel but not having it inserted at boot.

您似乎正在将Linux内核的概念与源代码树混为一谈. 将驱动程序的代码集成到linux内核中" 通常会解释为内置驱动程序,即该驱动程序被链接到内核中,并在引导时加载了内核映像的一部分.
存储在内核源代码树中的驱动程序代码无需指定是内置模块还是可加载模块.许多驱动程序(以及其他类型的模块)都可以构建,并且由构建配置指定哪个.

You seem to be conflating the concept of the Linux kernel with the source code tree.
"Driver's code integrated into linux kernel" would typically be interpreted to mean a built-in driver, that is the driver is linked in and part of the kernel image that is loaded at boot.
Whereas driver code that is stored in the kernel source tree confers no designation has to whether it is a built-in or a loadable module. Many drivers (and other types of modules) can be built as either, and it is the build configuration that specifies which.

如果您希望驱动程序成为可加载模块,那么(而不是更改设备树):

If you want your driver to be a loadable module, then (instead of changing the Device Tree):

a.您需要将驱动程序编码为适当的模块;
b.您需要修改 Kconfig 文件以在内置模块或可加载模块之间进行选择(即tristatebool选择规范).
C.配置内核以将驱动程序构建为可加载模块.

a. you need to code your driver as a proper module;
b. you need to modify the Kconfig file to choose between a built-in or loadable module (i.e. a tristate versus bool selection specification).
c. configure the kernel to build your driver as a loadable module.

在设备树中定义的,作为可加载模块的设备驱动程序仍可以在引导过程中自动加载和探测. 您可能必须使用模块黑名单来防止这种情况.

A device driver that is a loadable module and defined in the Device Tree could still be automatically loaded and probed during boot. You may have to use module blacklisting to prevent that.

**附录**

如何用可加载模块替换内置模块而无需重新编译内核以禁用内置模块?

How to replace a builtin module with a loadable one without recompiling kernel to disable the builtin module?

不能.因此,如果要构建该驱动程序,Kconfig会强制您在可加载模块(m)或内置模块(y)之间进行选择.

You can't. That's why Kconfig forces you to choose between a loadable module (m) or built-in (y) if you want that driver to be built.

...,然后,在完成所有操作后,使用补丁将这些修改添加到内置模块中.

... then, once everything has been done, add those modifications to the builtin moduleusing a patch.

这没有任何意义,因为您只需要驱动程序源的一个副本即可构建可加载模块或驱动程序的内置版本.

This makes no sense, since you only need a single copy of the driver source to build either a loadable module or a built-in version of the driver.

通过这种工作方式,我可以重建.ko并将其插入到我的目标平台上,而不必为每次修改重新编译内核.

With this way of working I can just rebuild the .ko and insert it on my target platform instead of recompiling a kernel for each modification.

似乎将驱动程序集成到内核源中的方式值得怀疑.
您实际上做了什么将驱动程序集成到内核源代码树中?
您为驱动程序修改了哪个 Kconfig Makefile ?
您为驱动程序创建了哪些新的CONFIG_ *符号?

Seems like how you integrated your driver into the kernel source is questionable.
What have you actually done to integrate your driver into the kernel source tree?
Which Kconfig and Makefile did you modify for your driver?
What new CONFIG_* symbol(s) did you create for your driver?

是的,您必须为每个修改重新编译" ,但是 make 足够聪明,可以仅重建必要的内容.当您知道只有可加载的驱动程序已被修改时,可以使用make modules进一步缩短内核重建时间.

Yes, you have to "recompile for each modification", but make is smart enough to rebuild only what is necessary. You could further shorten the kernel rebuild time by using make modules when you know that only your loadable driver has been modified.

要结论

  • 在不重新编译内核以禁用内置模块的情况下,无法使用树外可加载模块.

但是

  • 使用MM处仅重新编译一次内核,并将该模块列入内核引导行成功.
  • 仅在n处使用tristate重新编译内核一次.
  • Recompiling kernel only once with tristate at M and blacklisting the module on kernel boot line succeed.
  • Recompiling kernel only once with tristate at n succeed.

因此内核必须至少重新编译一次,但随后可以使用编译为可加载模块的树外驱动程序工作,而不必删除集成到linux源代码中的代码.

So the kernel has to be recompiled at least once, but then it's possible to work with an out-of-tree driver compiled as loadable module without having to remove the code integrated into linux sources.

这篇关于用可加载模块替换内核内置模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆