作者:全程解密_785 | 来源:互联网 | 2022-12-10 14:42
我已经开发了一个内核模块来将nf4标签作为char设备进行管理。
我已经在内核外部开发了该模块,并在开发阶段对其进行了测试,将其编译为可加载的内核模块(即.ko)。
一旦驱动程序正常运行并足够稳定,我便使用补丁将其插入linux内核源代码(v4.9.30),以便将其构建为内核的一部分。
这是我在模块所在的情况 已加载 在内核引导时对其进行探测,因为它是内置的,并出现在设备树中。
现在,我想在驱动程序上进行一些改进,并且不想将这些更改直接实现到内核中。
因此,我想将驱动程序的代码集成到Linux内核中,但不要在启动时将其插入。为此,我刚刚将驱动程序的status字段更改status = "disable";
为device-tree,实际上在启动时不再插入该模块。
但是我无法插入已修改的可加载模块。ENODEV
由于在platform函数中找不到beeinging设备,我插入了at。
我不明白的是,为什么除了状态字段值之外,没有更改设备树,为什么找不到平台设备。
编辑:添加有关情况的精度
经过更多的探索之后,我必须弄清楚我什至没有进入回调nf4_probe
。
将platform_driver_probe
实现(参见此处)检查到v4.9.30内核源代码后,似乎错误来自此处:
if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
retval = -ENODEV;
通过从命令行检查设备树,我可以看到该设备已定义为该目录/proc/device-tree/nf4tag
存在,并用与设备树中对应的值填充。
编辑: @sawdust的答案后,添加有关问题的目标的精度
我显然被误解了,这status=disable
意味着该设备在硬件配置上根本不存在。尽管只是描述了是否应该检测驱动程序。
为了使目标更清晰,我精确地确定了驱动程序已编码为适当的模块,并已编译为所用内核的可加载模块。
但是,我不想重新编译内核以测试我所做的每个更改。因此,我的目标是仅重新编译.ko,直到进行我的修改为止,然后,在完成所有操作后,使用补丁将这些修改添加到内置模块中。
通过这种工作方式,我可以重建.ko并将其插入到我的目标平台上,而不必为每次修改重新编译内核。
因此,恢复我的问题应该是:
如何用可加载模块替换内置模块而无需重新编译内核以禁用内置模块?
除了禁用内置模块编译到内核之外,也许没有针对此目标的解决方案。
1> sawdust..:
我不明白的是,为什么除了状态字段值之外,没有更改设备树,为什么找不到平台设备。
您似乎误解了该status = "disable"
属性的实际含义。
除了表示内核“不应在启动时插入”外,禁用节点还意味着该设备根本不属于当前硬件配置。
不管是内置模块还是可加载模块的驱动程序,都不会被探测,因为当前配置已禁用该驱动程序。
如果要使驱动程序(无论是内置模块还是可装入模块)处于当前配置中,则status = "okay"
在其“设备树”节点中具有一个属性。
IOW设备树用于描述内核的当前硬件配置。
不要尝试使用设备树来控制可加载模块(因为它不能)。
在这里,我处于一种情况,即模块在内置时由内核在引导时加载,并出现在设备树中。
该语句没有意义,因为您似乎同时将驱动程序描述为内置模块和可加载模块。
无需“加载”内置驱动程序即可调用其探测例程。
由于驱动程序可以是内置驱动程序,也可以是可加载驱动程序,因此“加载”和“探测”是两个不同的阶段,不应混为一谈。
因此,我想将驱动程序的代码集成到Linux内核中,但不要在启动时将其插入。
您似乎正在将Linux内核的概念与源代码树混为一谈。通常将
“集成到linux内核中的驱动程序代码”解释为内置驱动程序,即该驱动程序已链接到内核中,并且是引导时加载的内核映像的一部分。
存储在内核源代码树中的驱动程序代码无需指定是内置模块还是可加载模块。许多驱动程序(以及其他类型的模块)都可以构建,并且由构建配置指定。
如果希望驱动程序成为可加载模块,则(而不是更改设备树):
一种。您需要将驱动程序编码为适当的模块;
b。您需要修改Kconfig文件以在内置模块或可加载模块之间进行选择(即,tristate
与bool
选择规范相对)。
C。配置内核以将驱动程序构建为可加载模块。
在启动过程中,仍然可以自动加载和探测作为设备树中定义的可加载模块的设备驱动程序。您可能必须使用模块黑名单来防止这种情况。
**附录**
如何用可加载模块替换内置模块而无需重新编译内核以禁用内置模块?
你不能 因此,如果要构建该驱动程序,Kconfig会强制您在可加载模块(m
)或内置模块()中进行选择y
。
...然后,完成所有操作后,使用补丁将这些修改添加到内置模块中。
这没有任何意义,因为您只需要驱动程序源的一个副本即可构建可加载模块或驱动程序的内置版本。
通过这种工作方式,我可以重建.ko并将其插入到我的目标平台上,而不必为每次修改重新编译内核。
看来如何将驱动程序集成到内核源中是有问题的。
您实际上做了什么将驱动程序集成到内核源代码树中?您为驱动程序修改了
哪个Kconfig和Makefile?
您为驱动程序创建了哪些新的CONFIG_ *符号?
是的,您必须“为每个修改重新编译”,但是make足够聪明,可以仅重建必要的内容。make modules
当您知道只有可加载的驱动程序已被修改时,可以使用来进一步缩短内核的重建时间。
结论
如果不重新编译内核以禁用内置模块,就不可能使用树外可加载模块。
但
使用tristate
at 仅重新编译一次内核,M
并将该模块列入内核引导行的成功列表。
重新编译内核只有一次,tristate
在n
取得成功。
因此内核必须至少重新编译一次,但是随后可以使用树外驱动程序编译为可加载模块,而不必删除集成到linux源代码中的代码。