将内核内置模块替换为可加载模块

2024-04-11

我开发了一个内核模块来管理 nf4 标签作为字符设备。

我在内核之外开发了这个模块,并在开发阶段将其编译为可加载内核模块(即 .ko)进行了测试。

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

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.

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

所以我想将驱动程序的代码集成到Linux内核中,但不要在启动时插入它。 为此,我刚刚更改了驱动程序的状态字段status = "disable";到设备树中,实际上该模块在启动时不再插入。

但是我无法插入已修改的可加载模块。我有一个ENODEV插入时,这是由于在探测函数中未找到 platform_device 造成的。

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


EDIT:添加有关情况的精确度

经过更多探索后,我必须明确我什至没有进入回调nf4_probe.

检查后platform_driver_probe实施(见here https://elixir.bootlin.com/linux/v4.9.30/source/drivers/base/platform.c#L660)进入 v4.9.30 内核源代码,错误似乎来自这里:

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

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


EDIT:在 @sawdust 的回答后添加关于问题目的的精确性

我显然误解了status=disable意味着该设备根本不存在于硬件配置中。尽管它只是描述了是否应该对驾驶员进行调查。

为了使我的目标更清晰,我明确表示我确实将驱动程序编码为正确的模块,并将其编译为我正在使用的内核的可加载模块。

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

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

所以继续我的问题应该是:

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

除了禁用内置模块编译到内核之外,也许没有解决方案可以实现此目的。


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

你似乎误解了什么status = "disable"属性实际上意味着。
除此之外,这意味着内核应该“启动时没有插入它”,禁用的节点意味着该设备不是该设备的一部分current硬件配置全无。
驱动程序,无论是内置模块还是可加载模块,都不会被探测,因为它已针对当前配置被禁用。

如果您希望您的驱动程序(无论是内置模块还是可加载模块)处于当前配置,那么有一个status = "okay"其设备树节点中的属性。

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

在这里,我所处的情况是,模块在启动时由内核加载,因为它是内置的,并且它出现在设备树中。

这个声明没有任何意义,因为您似乎同时将驱动程序描述为内置模块和可加载模块。
不一定需要内置驱动程序"loaded"为了调用它的探测例程。
由于驱动程序可以是内置的或可加载的,因此“加载”和“探测”是两个不同的阶段,不应混为一谈。

所以我想将驱动程序的代码集成到Linux内核中,但不要在启动时插入它。

您似乎将 Linux 内核的概念与源代码树混为一谈。
“驱动程序代码集成到Linux内核中”通常会被解释为内置驱动程序,即驱动程序链接到启动时加载的内核映像中,并且是其一部分。
而存储在内核源代码树中的驱动程序代码则无需指定它是内置模块还是可加载模块。许多驱动程序(和其他类型的模块)可以built可以是其中之一,并且是构建配置指定的。

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

A。您需要将驱动程序编码为适当的模块;
b.你需要修改Kconfig文件来选择内置模块或可加载模块(即tristate versus bool选择规范)。
C。配置内核以将驱动程序构建为可加载模块。


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


** 附录 **

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

你不能。这就是为什么 Kconfig 强制您在可加载模块之间进行选择(m) 或内置 (y)如果您希望构建该驱动程序。

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

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

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

看来您如何将驱动程序集成到内核源代码中是有问题的。
您实际上做了什么来将驱动程序集成到内核源代码树中?
Which Kconfig and Makefile你修改了你的驱动程序吗?
您为驱动程序创建了哪些新的 CONFIG_* 符号?

是的,你必须“每次修改都重新编译”, but make足够聪明,可以只重建必要的部分。您可以通过使用进一步缩短内核重建时间make modules当您知道只有您的可加载驱动程序已被修改时。


结论

  • 如果不重新编译内核以禁用内置模块,就不可能使用树外可加载模块。

BUT

  • 仅重新编译内核一次tristate at M并将内核引导行上的模块列入黑名单成功。
  • 仅重新编译内核一次tristate at n成功。

因此内核必须至少重新编译一次,但是这样就可以使用编译为可加载模块的树外驱动程序,而无需删除集成到 Linux 源代码中的代码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将内核内置模块替换为可加载模块 的相关文章

  • 物理地址、设备地址和虚拟地址的区别

    有什么区别设备地址 实际地址 and 虚拟地址 其实我正在努力mmap在驱动程序中 我一直坚持这个概念 The 文档 https www kernel org doc Documentation DMA API HOWTO txt says
  • 加载内核模块时出现未知符号

    我需要帮助理解为什么在插入模块时出现错误 我努力了this http www linuxforums org forum kernel 56497 unkown symbol module error while insmodding bu
  • Linux 内核模块 Makefile 不能包含相对路径

    我正在尝试构建 Linux 内核模块 KBUILD EXTRA SYMBOLS Module symvers KBUILD EXTRA SYMBOLS dir0 Module symvers KDIR kernel linux 4 9 IN
  • Linux用户空间线程、内核线程、轻量级进程

    我对所有这些实体以及它们在 Linux 中如何互连感到有点困惑 Unix 内部原理 一书指出lightweight process LWP 是内核支持的用户线程 并且该内核看不到进程内的线程 对于 Linux 来说仍然如此吗 据我了解 用户
  • 如何用 C 语言从串行(SPI)连接读取数据?

    我正在尝试编写一个程序 该程序将安装在 Linux MCU Raspberry Pi 上 该程序将读取从另一个 MCU 我将自己构建的自制程序 发送到它的串行数据 我研究了如何做到这一点 并认为我有 大局 但仍然缺少一些东西 其一 我需要启
  • USB 端口速度 Linux [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何以编程方式确定运行 Linux 内核的嵌入式设备中的 USB 端口速度 你可以阅读 sys bus usb devices usb s
  • x86 平台中的 KVM 影子页表处理

    据我了解 在没有硬件支持来宾虚拟到主机物理地址转换的处理器上 KVM 使用影子页表 当来宾操作系统修改其页表时 会构建和更新影子页表 硬件中有没有专门的指令 以x86为参考 来修改页表 除非有特殊说明 否则不会对VMM 造成陷阱 Linux
  • 如何编写需要内核源头文件的 BitBake 驱动程序配方?

    介绍 我有一个do install我为驱动程序编写的 BitBake 配方中的任务 我在其中执行自定义install脚本 任务失败 因为安装脚本无法在其中找到内核源头文件
  • 是否可以将 CFLAGS 设置为 Linux 内核模块 Makefile?

    例如 常见设备模块的Makefile obj m jc o default MAKE C lib modules shell uname r build M shell pwd modules clean MAKE C lib module
  • ARM 系统调用的接口是什么?它在 Linux 内核中的何处定义?

    我读过有关 Linux 中的系统调用的内容 并且到处都给出了有关 x86 架构的描述 0x80中断和SYSENTER 但我无法追踪 ARM 架构中系统调用的文件和进程 任何人都可以帮忙吗 我知道的几个相关文件是 arch arm kerne
  • perf 找不到外部模块符号

    跑步时perf它找到了我的程序的内核符号和符号 但没有找到外部模块符号 我已经编写了一个内核模块 我使用它加载insmod我怎么知道perf也找到它的符号 我正在运行 2 6 37 6 内核 无法升级 我的perf尚不支持矮人选项 但我认为
  • 如何在 Linux x86_64 上模拟 iret

    我正在编写一个基于 Intel VT 的调试器 由于当 NMI Exiting 1 时 iret 指令在 vmx guest 中的性能发生了变化 所以我应该自己处理vmx主机中的NMI 否则 guest会出现nmi可重入错误 我查了英特尔手
  • modinfo srcversion:如何从我的源生成此版本?

    我有一个 Linux 模块的编译版本 然后我有大约 20 多个其源代码的变体 由于各种愚蠢的错误 我已经不知道哪个版本的源代码是我用来制作模块的实际版本了 我注意到modinfo
  • 是否从页面缓存中的脏页面进行文件读取?

    当字节写入文件时 内核不会立即将这些字节写入磁盘 而是将这些字节存储在页缓存中的脏页中 回写缓存 问题是 如果在脏页刷新到磁盘之前发出文件读取 则将从缓存中的脏页提供字节 还是首先将脏页刷新到磁盘 然后进行磁盘读取以提供字节 将它们存储在进
  • 在Linux中断上下文中运行用户线程

    我正在编写一些定制的应用程序 并允许更改 Linux 内核中的中断处理程序代码 我有一个用户线程正在等待中断发生 如果发生中断 那么我要做的第一件事就是执行该用户线程 有什么办法让它发挥作用吗 Thanks 创建一个字符设备 这就是内核所做
  • 动态更改 eBPF 映射大小

    在内核中 eBPF 映射可以定义为 struct bpf map def SEC maps my map type BPF MAP TYPE HASH key size sizeof uint32 t value size sizeof s
  • 同步 I/O 是否会使线程繁忙?

    假设我正在同步 I O 套接字上执行 I O 该套接字已准备好read or write手术 这意味着调用线程不会在操作上被阻塞 无论非阻塞 SOCK NONBLOCK 套接字的阻塞性质 但以下事情我不清楚 实际转移何时发生 当套接字标记为
  • 如何模拟ARM处理器运行环境并加载Linux内核模块?

    我尝试加载我的vmlinux into gdb并使用 ARM 内核模拟器 但我不明白为什么我会得到Undefined target command sim 这是外壳输出 arm eabi gdb vmlinux GNU gdb GDB 7
  • 内存调试:如何获取 Linux 用户空间/内核空间中的锁定页面信息

    有什么方法可以获取Linux用户空间 内核空间中的锁定页面 虚拟内存页面 信息 我想了解详细信息 例如 谁锁定了页面 有多少页被锁定 进程名称 谁锁定了页面 还让我了解内核空间和用户空间的内存调试技术 对于内存中的每个页面 都会为其分配标志
  • 使用sk_buff添加以太网帧头

    我有一个捕获传出互联网流量的内核模块 Netfilter hook LOCAL OUT 在此挂钩处 仍然没有以太网标头 我构建了以太网头并且可以使用了 但是如何将其连接到skb这样我就可以将整个 skb 结构发送到dev queue xmi

随机推荐

  • 将 numpy 数组转换为十六进制字节数组

    我想在 python 2 7 中将 numpy 数组转换为字节串 比如说我的 numpy 数组a是一个简单的2x2数组 看起来像这样 1 10 16 255 我的问题是 如何将此数组转换为字节字符串或字节数组 输出如下 x01 x0A x1
  • 如何使用webpack导入静态url

    如何使用 webpack 导入静态 url index js import http google com myscript js 确实不清楚你想做什么 但总的来说你有几个选择 预先下载脚本或通过 NPM 安装 这可能是处理外部依赖关系的首
  • Ruby on Rails robots.txt 文件夹

    我即将启动 Ruby on Rails 应用程序 作为最后一个任务 我想设置机器人 txt文件 我找不到有关如何为 Rails 应用程序正确编写路径的信息 起始路径是否始终是 Ruby on Rails 应用程序或应用程序文件夹的根路径 那
  • 启用 iCloud 时 iOS 应用程序在首次启动时冻结

    我在 iOS 应用程序中启用了 iCloud 并且在首次启动应用程序时 当我按下应用程序中的任何视图时 应用程序会冻结大约 5 秒 我跟着this http timroadley com 2012 04 03 core data in ic
  • GitHub - 当非默认分支与主分支合并时,PR 链接的问题不会被关闭

    I have main作为默认分支和dev作为非默认 我创建了一个问题和一个 PR 以从新的合并temp分支到dev分支 在公关中 我曾提到过Resolves 1 当我将 PR 合并到dev分支 问题 1不会关闭 因为它是非默认分支 然后我
  • 使用 STM32F0 ADC 单独读取不同的输入

    STM32F072CBU 微控制器 我有多个 ADC 输入 并且希望单独读取它们 STMcubeMX 生成样板代码 假设我希望按顺序读取所有输入 但我无法弄清楚如何纠正这个问题 这篇博文 http blog koepi info 2015
  • 如何在本地执行 Capistrano 任务?

    我定义了一个自定义 Capistrano 任务 该任务应该在本地运行 在我的开发计算机上 desc Push code to Dreamhost task push do run git push dreamhost end 但是当我尝试跑
  • python dask DataFrame,支持(可并行化)行应用吗?

    我最近发现dask http dask pydata org en latest index html旨在成为一个易于使用的 python 并行处理模块 对我来说最大的卖点是它可以与熊猫一起使用 在阅读了其手册页后 我找不到一种方法来完成这
  • 如何获取Python字典中的最高键?

    d 苹果 9 橙子 3 葡萄 22 如何返回最大的键 值 编辑 如何制作一个按最大到最低值排序的列表 gt gt gt d apple 9 oranges 3 grapes 22 gt gt gt v k max v k for k v i
  • 包 inputenc 错误:Unicode char \u8:β 未设置为与 LaTeX 一起使用

    我在 Bibdesk 中的参考文献之一包含一些拉丁 希腊字符 例如 我在 TEXMAKER 中使用参考时收到错误 包 inputenc 错误 Unicode char u8 未设置为与 LaTeX 一起使用 我该如何设置它才能工作 尽管使用
  • 数据按用户分组为每周、每月

    我有一个高库存折线图 显示给定股票的每日和每周股价 问题是 当数据数组足够大时 每日数据点将被 采样 为每周数据点 而每周数据点将被采样为每月数据点 有什么方法可以根据需要将用户设置为每周或每月 提前致谢 检查一下数据分组 http www
  • 返回时如何刷新片段 UI

    我是 Android 新手 正在学习片段的知识 并为其制作了一个演示 因为我有一个片段 我们可以从中转到另一个活动 那里正在执行一些计算 然后我们当时回到片 段我想将该计算值显示到我的片段的文本视图中 那么我应该使用哪种生命周期方法来执行此
  • TypeError:无法解压不可迭代的 NoneType 对象

    我知道这个问题之前已经被问过 但我似乎无法让我的问题工作 import numpy as np def load dataset def download filename source http yaan lecun com exdb m
  • 如何从store方法获取上传的图片名称

    当我在 Laravel 中存储图像时 path request gt file myImage gt store public src 它返回完整路径 但如何仅获取给定的文件名 这是返回路径的示例 public src ltX4COwEmv
  • JPackages JavaFX + Spring boot 无法启动

    我正在尝试使用 Spring Boot 构建 JavaFX 应用程序并使用 jpackage 进行部署 当使用javafx maven plugin javafx run命令 我可以看到项目启动 但在将其构建为 msi安装程序 安装并启动
  • 使用 rvmrc 或 ruby​​-version 文件通过 RVM 设置项目 gemset?

    我使用RVM Ruby 版本管理器 https rvm io 为我的每个 Rails 项目指定 Ruby 版本和一组 gem 我有一个 rvmrc文件来自动选择 Ruby 版本和 gemset 每当我cd进入项目目录 安装 RVM 1 19
  • git-p4 正在吃掉我的图像文件

    所以 我可以使用 git p4 从 p4 导入 没有任何问题 一切似乎都正常 但我的 PNG 文件 也许还有其他文件 正在损坏 我读过有关 gitattributes 和行结束问题的内容 但我所做的一切似乎都无法改变最终结果 破碎的图像 我
  • 如何使用 joblib.dump 在 s3 上保存 sklearn 模型?

    我有一个 sklearn 模型 我想使用 joblib dump 将 pickle 文件保存在我的 s3 存储桶上 I used joblib dump model model pkl 将模型保存到本地 但我不知道如何将其保存到 s3 存储
  • C、C++ 初始化中的排序

    考虑以下初始化 C C int a f g struct int x y foo f g C struct goo goo int x int y goo b f g goo c f g C 11 goo d f g 是执行顺序f and
  • 将内核内置模块替换为可加载模块

    我开发了一个内核模块来管理 nf4 标签作为字符设备 我在内核之外开发了这个模块 并在开发阶段将其编译为可加载内核模块 即 ko 进行了测试 一旦驱动程序功能正常且足够稳定 我就使用补丁将其插入 Linux 内核源代码 v4 9 30 以便