Compile-kernel-module

Compile-kernel-module

1. 内核模块编程
1.1 简介
1.2 加载内核模块
1.3 最简单的模块
1.4 模块必要信息
1.4.1 内核模块必须至少包含的头文件:
1.4.2 内核模块必须至少有两个功能:
1.4.3 printk()日志记录
1.4.4 优先级
1.4.5 许可和模块文档
1.5 编译内核模块
1.6 实战
1.6.1 源代码文件: hello.c
1.6.2 Makefile文件: Makefile
1.6.3 使用make编译
1.6.4 使用modinfo查看新的模块文件
1,6.5 使用insmod加载内核模块
1.6.6 使用lsmod查看已加载的模块
1.6.7 使用rmmod卸载模块
1.6.8 使用dmesg查看日志
1.6.9 练习
1.6.10 其他信息
1.7 更多基础示例链接
1.7.1 将命令行参数传递给模块
1.7.2 跨越多个文件的模块
1.7.3 构建预编译内核的模块
1.7.4 与应用程序交互
2 make工具
2.1 DESCRIPTION
2.2 退出状态
2.3 选项
3. 其他内核编译方法及相关连接
3.1 编译Arch的内核模块
3.2 Arch构建系统
3.3 内核/传统编译
3.4 修补包
3.5 模块与程序

1. 内核模块编程

http://www.tldp.org/LDP/lkmpg/2.6/html/
Linux内核模块编程指南 2007-05-18见2.6.4

1.1 简介

什么是内核模块?模块是可以根据需要加载和卸载到内核中的代码片段。它们扩展了内核的功能,而无需重启系统。
例如,一种类型的模块是设备驱动程序,它允许内核访问连接到系统的硬件。还有很多的文件系统等。

1.2 加载内核模块

您可以通过运行lsmod来查看已经加载到内核中的模块,lsmod通过读取文件/proc/modules来获取其信息。
执行modprobe来加载模块.modprobe以两种形式之一传递一个字符串:
  > 模块名称,如softdog或ppp。
  > 一个更通用的标识符,如char-major-10-30。
如果modprobe被赋予通用标识符,它首先在文件/etc/modprobe.conf中查找该字符串。如果找到如下的别名行:alias char-major-10-30 softdog
它知道通用标识符引用模块softdog.ko。
然后,modprobe查看文件/lib/modules/version/modules.dep,查看是否必须加载其他模块才能加载所请求的模块。该文件由depmod -a创建,包含模块依赖项。
      例如,msdos.ko要求fat.ko模块已经加载到内核中。
最后,modprobe使用insmod首先将任何必备模块加载到内核中,然后加载所请求的模块。
modprobe将insmod指向/lib/modules/'uname -r'/, 模块的标准目录。

insmod对于模块的位置是相当愚蠢的,而modprobe知道模块的默认位置,知道如何找出依赖关系并以正确的顺序加载模块。
因此,例如,如果要加载msdos模块,则必须运行:
$ insmod /lib/modules/2.6.11/kernel/fs/fat/fat.ko
$ insmod /lib/modules/2.6.11/kernel/fs/msdos/msdos.ko

要么:
$ modprobe msdos
所以,insmod要求你传递完整的路径名并以正确的顺序插入模块,而modprobe只取名字,没有任何扩展名,并通过解析/lib找出它需要知道的所有内容/modules/version/modules.dep。

1.3 最简单的模块

http://www.tldp.org/LDP/lkmpg/2.6/html/x121.html
Example 2-1. hello-1.c
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
int init_module(void)
{
printk(KERN_INFO "Hello world 1.\n");
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}

1.4 模块必要信息

1.4.1 内核模块必须至少包含的头文件:

#include <linux/module.h> /* module_init() module_exit() 函数来注册模块入口和退出处理。
#include <linux/kernel.h> /* Needed for KERN_INFO ,仅用于printk()日志级别的KERN_ALERT的宏扩展 */
#include <linux/init.h> /* Needed for the macros */

1.4.2 内核模块必须至少有两个功能:

  • 一个“开始”(初始化)功能调用 的init_module()当模块insmoded到内核被称为,
  • 以及“结束”(清理)函数调用在cleanup_module()这是刚刚称为在它被破坏之前。
从Linux 2.4开始,您可以重命名模块的init和cleanup功能; 它们不再需要分别被称为 init_module()和cleanup_module()。
这是通过 module_init()和module_exit()宏完成的。这些宏在linux / init.h中定义。
唯一需要注意的是,必须在调用宏之前定义init和cleanup函数,否则会出现编译错误。

1.4.3 printk()日志记录

由于代码运行在内核空间里面,不能直接使用用户空间的 print 函数,而要使用内核中的 printk 函数.
作为日志记录机制,用于记录信息或发出警告。
每个printk() 语句都带有一个优先级,即您看到的<1>和KERN_ALERT。
有8个优先级,内核有宏,所以你不必使用神秘的数字,你可以在linux/kernel.h中查看它们(及其含义)。
如果未指定优先级,则将使用默认优先级DEFAULT_MESSAGE_LOGLEVEL。

花点时间阅读优先级宏。头文件还描述了每个优先级的含义。
在实践中,不要使用数字,如<4>。始终使用宏,如 KERN_WARNING。

如果优先级低于int console_loglevel,则会在当前终端上打印消息。
如果syslogd和klogd都在运行,那么该消息也将附加到/var/log/messages,无论它是否打印到控制台。
我们使用高优先级(如KERN_ALERT)来确保将printk()消息打印到控制台而不是仅记录到日志文件中。
编写实际模块时,您需要使用对当前情况有意义的优先级。

1.4.4 优先级

https://szosoft.blogspot.com/2019/06/linux-journal.html#1021
cat  /usr/lib/modules/5.1.15-arch1-1-ARCH/build/include/linux/kernel.h
cat  /usr/lib/modules/5.1.15-arch1-1-ARCH/build/include/linux/printk.h
内核模块printkno(Key)journal
KERN_EMERG0Emergency 紧急
KERN_ALERT1Alert 警报
KERN_CRIT2Critical 危急
KERN_ERR3Error 错误
KERN_WARNING4Warning 警告
KERN_NOTICE5Notice 注意
KERN_INFO6Informational 信息
KERN_DEBUG7Debug 调试

1.4.5 许可和模块文档

MODULE_LICENSE("GPL");  /* Get rid of taint message by declaring code as GPL.  */
MODULE_AUTHOR("Tom"); /* Who wrote this module? */
MODULE_DESCRIPTION("Test"); /* What does this module do */
MODULE_VERSION("0.0.1");
MODULE_SUPPORTED_DEVICE("testdevice");   /* 声明模块支持哪些类型的设备。 */
在内核2.4及更高版本中,设计了一种机制来识别在GPL(和朋友)下许可的代码,以便可以警告人们代码是非开源的。
这是通过MODULE_LICENSE()宏实现的。通过将许可证设置为GPL,可以防止打印警告。
此许可证机制在linux/module.h中定义并记录:
$ cat  /usr/lib/modules/5.1.15-arch1-1-ARCH/build/include/linux/module.h |grep MODULE_

/*
 * 目前接受以下许可证标识为免费软件模块
 * "GPL" [GNU Public License v2 or later]
 * "GPL v2" [GNU Public License v2]
 * "GPL and additional rights" [GNU Public License v2 rights and more]
 * "Dual BSD/GPL" [GNU Public License v2 or BSD license choice]
 * "Dual MIT/GPL" [GNU Public License v2 or MIT license choice]
 * "Dual MPL/GPL" [GNU Public License v2 or Mozilla license choice]
 *
 * 以下其他标识可供选择
 * "Proprietary" [Non free products]
 */

1.5 编译内核模块

http://www.tldp.org/LDP/lkmpg/2.6/html/x181.html
内核模块的编译需要与常规用户空间应用程序略有不同。
以前的内核版本要求我们关注这些设置,这些设置通常存储在Makefile中。虽然按层次结构组织,但许多冗余设置在次级Makefile中累积并使它们变大并且难以维护。
幸运的是,有一种新方法可以做这些事情,称为kbuild,外部可加载模块的构建过程现在完全集成到标准内核构建机制中。
要了解有关如何编译不属于官方内核的模块的更多信息(例如本指南中的所有示例),请参阅文件 linux/Documentation/kbuild/modules.txt.

编译时通过一个 Makefile 文件进行,把这个 Makefile 文件置于 hello.c 同一目录下.
Makefile对格式有要求。每一行文本除非顶头开始,如果需要格式编排,不能使用空格键来控制文本行 缩进,必须使用Tab键

1.6 实战

1.6.1 源代码文件: hello.c

/*  hello.c - Demonstrates module documentation. */
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#define DRIVER_AUTHOR "Peter Jay Salzman <p@dirac.org>"
#define DRIVER_DESC   "A sample driver"

static int __init init_hello(void)
{
printk(KERN_INFO "HelloWorld\n");
return 0;
}

static void __exit cleanup_hello(void)
{
printk(KERN_INFO "GoodbyeWorld\n");
}

module_init(init_hello);
module_exit(cleanup_hello);

MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR); /* Who wrote this module? */
MODULE_DESCRIPTION(DRIVER_DESC); /* What does this module do */
MODULE_SUPPORTED_DEVICE("testdevice");

1.6.2 Makefile文件: Makefile

obj-m += hello.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

从技术角度来看,第一行确实是必要的,为了方便起见,添加了“全部”和“清洁”目标。
现在您可以通过发出命令make来编译模块。您应该获得类似于以下内容的输出:

1.6.3 使用make编译

$ make
make -C /lib/modules/5.1.15-arch1-1-ARCH/build M=/home/toma/ko modules
make[1]: Entering directory '/usr/lib/modules/5.1.15-arch1-1-ARCH/build'
  CC [M]  /home/toma/ko/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/toma/ko/hello.mod.o
  LD [M]  /home/toma/ko/hello.ko
make[1]: Leaving directory '/usr/lib/modules/5.1.15-arch1-1-ARCH/build'

请注意,内核2.6引入了一种新的文件命名约定:内核模块现在具有.ko 扩展名(代替旧的.o扩展名),可以轻松地将它们与传统的目标文件区分开来。
原因是它们包含一个额外的.modinfo部分,其中保留了有关该模块的其他信息。我们很快就会看到这些信息有什么用处。
有关内核模块的Makefile的更多详细信息,请参见 linux/Documentation/kbuild/makefiles.txt .

$ ls -l   //编译后查看文件列表
name size
Makefile 154   //make文件
hello.c 786      //源文件
hello.ko 4528   //内核文件
hello.mod.c 646
hello.mod.o 2712
hello.o 2664   //目标文件
modules.order 30
Module.symvers 0

1.6.4 使用modinfo查看新的模块文件

$ modinfo hello.ko
filename:       /home/toma/ko/hello.ko
version:        0.0.1
description:    Test
author:         Tom
license:        GPL
srcversion:     BC3C3A49026E0297D738AE7
depends:      
retpoline:      Y
name:           hello
vermagic:       5.1.15-arch1-1-ARCH SMP preempt mod_unload

1,6.5 使用insmod加载内核模块

$ sudo insmod ./hello.ko

1.6.6 使用lsmod查看已加载的模块

$ lsmod |grep hello
Module                  Size  Used by
hello                  16384  0

1.6.7 使用rmmod卸载模块

$ sudo rmmod hello
$ lsmod |grep hello

1.6.8 使用dmesg查看日志

$ dmesg |tail
...
[562050.818179] HelloWorld
[562458.113633] GoodbyeWorld

1.6.9 练习

练习1
请参阅init_module()中 return语句上方的注释 ?将返回值更改为负值,重新编译并再次加载模块。怎么了?
$ sudo insmod ./hello-2.ko
insmod: ERROR: could not insert module ./hello-2.ko: Operation not permitted
$ dmesg |tail
...
[546135.110381] HelloWorld2.

练习2
将代码中许可的部分删除,再编译看看。
$ make
make -C /lib/modules/5.1.15-arch1-1-ARCH/build M=/home/toma/ko modules
make[1]: Entering directory '/usr/lib/modules/5.1.15-arch1-1-ARCH/build'
  CC [M]  /home/toma/ko/hello-1.o
  Building modules, stage 2.
  MODPOST 1 modules
style="color: red; font-size: xx-small;">WARNING: modpost: missing MODULE_LICENSE() in /home/toma/ko/hello-1.o
see include/linux/module.h for more information
  CC      /home/toma/ko/hello-1.mod.o
  LD [M]  /home/toma/ko/hello-1.ko
make[1]: Leaving directory '/usr/lib/modules/5.1.15-arch1-1-ARCH/build'

1.6.10 其他信息

现在看一下linux/drivers/char/Makefile的真实示例。
正如你所看到的,有些东西被硬件连接到内核(obj-y)但是那些obj-m去了哪里?
那些熟悉shell脚本的人很容易发现它们。
对于那些没有的,你看到的obj - $(CONFIG_FOO)条目会扩展为obj-y或obj-m,具体取决于CONFIG_FOO变量是否已设置为y或m。
虽然我们在这里,但那些正是你在linux/.config文件中设置的那种变量,最后一次你说make menuconfig 或类似的东西。

1.7 更多基础示例链接

1.7.1 将命令行参数传递给模块

http://www.tldp.org/LDP/lkmpg/2.6/html/x323.html

1.7.2 跨越多个文件的模块

http://www.tldp.org/LDP/lkmpg/2.6/html/x351.html

1.7.3 构建预编译内核的模块

http://www.tldp.org/LDP/lkmpg/2.6/html/x380.html

1.7.4 与应用程序交互

https://www.oschina.net/translate/writing-a-simple-linux-kernel-module

2 make工具

2.1 DESCRIPTION

make实用程序将自动确定需要重新编译大型程序的哪些部分,并发出命令以重新编译它们。
我们的示例显示了C程序,因为它们非常常见,但您可以使用make与任何编译语言,其编译器可以使用shell命令运行。
实际上,make并不仅限于程序。
您可以使用它来描述任何一些任务,其中某些文件必须在其他文件更改时自动从其他文件更新。

要准备使用make,您必须编写一个名为makefile的文件,该文件描述程序中文件之间的关系,以及用于更新每个文件的命令的状态。
在程序中,通常从目标文件更新可执行文件,而目标文件又通过编译源文件来完成。

一旦存在合适的makefile,每次更改一些源文件时,这个简单的shell命令:
make
足以执行所有必要的重新编译。
make程序使用makefile描述和文件的最后修改时间来决定需要更新哪些文件。
对于每个文件,它会发出makefile中记录的命令。

make执行makefile中的命令以更新一个或多个目标名称,其中name通常是程序。
如果不存在-f选项,make将按顺序查找 makefiles GNUmakefile, makefile, and Makefile, in that order.

(我们建议使用Makefile,因为它突出显示在目录列表的开头附近,紧邻其他重要文件,如README。)
检查的第一个名称,建议不要将GNUmakefile用于大多数makefile。
如果您具有特定于GNU make的makefile,则应使用此名称,并且其他版本的make不会理解该名称。
如果makefile为' - ',则读取标准输入。

2.2 退出状态

如果所有的makefile都被成功解析并且没有构建的目标失败,则GNU make退出状态为零。
如果使用-q标志并且make确定需要重建目标,则将返回状态1。
如果遇到任何错误,将返回状态2。

2.3 选项

-b, -mIgnored for compatibility.忽略兼容性.
-B, --always-makeUnconditionally make all targets.无条件地制定所有目标.
-C DIRECTORY, --directory=DIRECTORYChange to DIRECTORY before doing anything.在做任何事之前改为DIRECTORY.
-dPrint lots of debugging information.打印大量调试信息.
--debug[=FLAGS]Print various types of debugging information. FLAGS可以用于所有调试输出(与使用-d相同),
b用于基本调试,v用于更详细的基本调试,i用于显示隐式规则,
j用于调用命令的详细信息,m用于在重新生成makefile时进行调试.
 使用n禁用所有先前的调试标志.
-e, --environment-overridesEnvironment variables override makefiles.环境变量覆盖makefile.
--eval=STRINGEvaluate STRING as a makefile statement.将STRING评估为makefile语句.
-f FILE, --file=FILE, --makefile=FILERead FILE as a makefile.将FILE作为makefile读取.
-h, --helpPrint this message and exit.打印此消息并退出.
-i, --ignore-errorsIgnore errors from recipes. 忽略为重制文件而执行的命令中的所有错误.
-I DIRECTORY, --include-dir=DIRECTORYSearch DIRECTORY for included makefiles.搜索DIRECTORY以获取包含的makefile.
-j [N], --jobs[=N]Allow N jobs at once; infinite jobs with no arg.一次允许N个工作;没有arg的无限工作.
-k, --keep-goingKeep going when some targets can't be made.当一些目标无法制作时继续前进.
-l [N], --load-average[=N],--max-load[=N]Don't start multiple jobs unless load is below N.除非负载低于N,否则不要启动多个作业.
-L, --check-symlink-timesUse the latest mtime between symlinks and target.使用符号链接和目标之间的最新mtime.
-n, --just-print, --dry-run, --reconDon't actually run any recipe; just print them.实际上不要运行任何配方;只需打印它们.
-o FILE, --old-file=FILE, --assume-old=FILEConsider FILE to be very old and don't remake it.即使FILE很老,也不要重新生成它.
-O[TYPE], --output-sync[=TYPE]Synchronize output of parallel jobs by TYPE.按TYPE同步并行作业的输出.
 当与-j并行运行多个作业时,请确保将每个作业的输出收集在一起,而不是穿插其他作业的输出.
 如果未指定type或是target,则将每个目标的整个配方的输出组合在一起.
 如果type为line,则配方中每个命令行的输出将组合在一起.
 如果type是recurse,则整个递归make的输出被组合在一起.
如果type为none,则禁用输出同步.
-p, --print-data-basePrint make's internal database. 打印通过读取makefile产生的数据库(规则和变量值);
然后像往常一样或以其他方式指定执行.
要打印数据库而不尝试重新创建任何文件,请使用: make -p -f/dev/null.
-q, --questionRun no recipe; exit status says if up to date.``问题模式''.不要运行任何命令,也不要打印任何东西;如果指定的目标已经是最新的,则返回退出状态为零,否则返回非零值.
-r, --no-builtin-rulesDisable the built-in implicit rules.禁用内置隐式规则.
-R, --no-builtin-variablesDisable the built-in variable settings.禁用内置变量设置.
-s, --silent, --quietDon't echo recipes. 无声操作;不要在执行时打印命令.
-S, --no-keep-going, --stopTurns off -k. 取消-k选项的效果.这是永远不必要的,
除了在递归make中,-k可能通过MAKEFLAGS从顶级make继承,
或者如果你在环境中的MAKEFLAGS中设置-k.
-t, --touchTouch targets instead of remaking them.触摸目标而不是重新制作它们.
 这用于假装命令已完成,以欺骗未来的make调用.
--tracePrint tracing information.打印跟踪信息.
-v, --versionPrint the version number of make and exit.打印make和exit的版本号.
-w, --print-directoryPrint the current directory.打印当前目录.
--no-print-directoryTurn off -w, even if it was turned on implicitly.关闭-w,即使它是隐式打开的.
-W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILEConsider FILE to be infinitely new.认为FILE是无限新的.
 没有-n,它几乎与在运行make之前在给定文件上运行touch命令相同,只是修改时间仅在make的想象中改变.
--warn-undefined-variablesWarn when an undefined variable is referenced.引用未定义的变量时发出警告.

3. 其他内核编译方法及相关连接

3.1 编译Arch的内核模块

https://wiki.archlinux.org/index.php/Compile_kernel_module
首先,您需要安装构建依赖项,例如compiler(base-devel)和linux-headers。

3.2 Arch构建系统

https://wiki.archlinux.org/index.php/Kernel/Arch_Build_System
https://www.kernel.org/doc/Documentation/kbuild/kconfig.txt
内核/Arch构建系统
该拱门构建系统可以用来构建基于官方的自定义内核的Linux软件包。
这种编译方法可以自动化整个过程,并且基于经过良好测试的软件包。
您可以编辑PKGBUILD以使用自定义内核配置或添加其他修补程序。
$ pacman -Ss asp
extra/asp 5-1    Arch Linux build source file management tool
安装的ASP封装和基devel的包组。
您需要一个干净的内核来开始自定义。通过运行以下命令从ABS获取最新的内核包文件到您的构建目录:
$ asp update linux
$ asp checkout linux
然后,从各自的源获取您需要的任何其他文件(例如,自定义配置文件,修补程序等)。

3.3 内核/传统编译

https://wiki.archlinux.org/index.php/Kernel/Traditional_compilation#Download_the_kernel_source
安装核心包
安装base-devel软件包组,其中包含必要的软件包,例如make和gcc。
还建议安装以下软件包,如默认的Arch内核PKGBUILD中所列:xmlto,kmod,inetutils,bc,libelf,git

3.4 修补包

https://wiki.archlinux.org/index.php/Patching_packages#Applying_patches
本文介绍如何创建以及如何在Arch Build System(ABS)中将补丁应用于包。
一个补丁描述了一组针对一个或多个文件线路的变化。补丁通常用于自动更改源代码。

3.5 模块与程序

http://www.tldp.org/LDP/lkmpg/2.6/html/x427.html
程序 模块
用户空间      内核空间
printf() printk()
main()开始 init_module或 通过module_init调用指定的函数 开始
  cleanup_module或 使用module_exit调用指定的函数 结束
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Buildroot 中,`eval` 命令的作用是在构建过程中动态执行一个字符串作为 Shell 命令。`kernel-module` 是 Buildroot 中用于构建 Linux 内核模块的选项之一。因此,`eval kernel-module` 的作用是动态执行一个字符串以构建 Linux 内核模块。 具体用法如下: 1. 在 Buildroot 的 `make` 命令中添加 `BR2_PACKAGE_CUSTOM_KERNEL_MODULES=y`,启用自定义内核模块选项。 2. 在 `package/Config.in` 文件中添加以下代码,定义内核模块选项: ``` config BR2_PACKAGE_MY_KERNEL_MODULE bool "My Kernel Module" help Build and install my custom kernel module ``` 3. 在 `package/my_kernel_module/` 目录下创建以下文件: - `my_kernel_module.mk`:定义内核模块的构建规则。 - `my_kernel_module.modprobe`: 定义内核模块的 modprobe 配置文件。 4. 在 `my_kernel_module.mk` 中,使用以下代码定义内核模块的构建规则: ``` MY_KERNEL_MODULE_VERSION = 1.0 MY_KERNEL_MODULE_SITE = $(TOPDIR)/../my_kernel_module MY_KERNEL_MODULE_SITE_METHOD = local define MY_KERNEL_MODULE_BUILD_CMDS $(MAKE) -C $(@D) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(TARGET_CROSS) \ KERNELDIR=$(LINUX_DIR) M=$(PWD) modules endef define MY_KERNEL_MODULE_INSTALL_TARGET_CMDS $(INSTALL) -D -m 644 $(@D)/my_kernel_module.ko \ $(TARGET_DIR)/lib/modules/$(KERNEL_VERSION)/extra/my_kernel_module.ko endef $(eval $(kernel-module)) ``` 这里,`MY_KERNEL_MODULE_VERSION` 指定内核模块的版本号,`MY_KERNEL_MODULE_SITE` 指定内核模块的源代码目录,`MY_KERNEL_MODULE_SITE_METHOD` 指定内核模块的源代码获取方式(这里是本地目录),`MY_KERNEL_MODULE_BUILD_CMDS` 定义内核模块的构建命令,`MY_KERNEL_MODULE_INSTALL_TARGET_CMDS` 定义将内核模块安装到目标系统的命令。 5. 在 `my_kernel_module.modprobe` 文件中定义内核模块的 modprobe 配置信息: ``` alias my_kernel_module my_kernel_module.ko ``` 6. 最后,在 Buildroot 的菜单配置界面中,选择 `Target packages -> Hardware handling -> Kernel modules -> My Kernel Module`,使 Buildroot 构建系统包含您的自定义内核模块。 在 Buildroot 构建系统构建完成后,您的自定义内核模块将被编译并安装到目标系统中,可以使用 modprobe 命令加载和卸载该模块。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值