如何将Linux内核驱动程序模块添加为Buildroot包?

我目前正在为Xilinx的Zybo Board构建嵌入式Linux。 为此,我使用Buildroot。 现在我想添加一个用C语言编写的驱动程序 ,用户程序可以使用该驱动程序写入某些特定的寄存器,使其能够控制某些LED。 当我查看手册时 ,它基本上说首先要做的是在新的包文件夹中创建一个Config.in,在那里你可以写一些文字来解释驱动程序。 好的,我做到了。 但是现在makefile:我不太明白那里需要什么。 它只是一个像gcc -o ledcontrol hellofunc.c这样的编译命令吗? 除了Config.in和Makefile之外,我还需要做些什么吗?

您正在寻找的是内核模块基础架构 。您可以在这里查看Buildroot手册:

https://buildroot.org/downloads/manual/manual.html#_infrastructure_for_packages_building_kernel_modules

或者在使用Buildroot提供的内核模块基础结构的众多示例中,它帮助内核模块添加到Buildroot:

 $ git grep "(kernel-module)" -- package/ package/amd-catalyst/amd-catalyst.mk:$(eval $(kernel-module)) package/batman-adv/batman-adv.mk:$(eval $(kernel-module)) package/cryptodev-linux/cryptodev-linux.mk:$(eval $(kernel-module)) package/emlog/emlog.mk:$(eval $(kernel-module)) package/freescale-imx/kernel-module-imx-gpu-viv/kernel-module-imx-gpu-viv.mk:$(eval $(kernel-module)) package/igh-ethercat/igh-ethercat.mk:$(eval $(kernel-module)) package/iqvlinux/iqvlinux.mk:$(eval $(kernel-module)) package/ktap/ktap.mk:$(eval $(kernel-module)) package/linux-backports/linux-backports.mk:$(eval $(kernel-module)) package/lttng-modules/lttng-modules.mk:$(eval $(kernel-module)) package/nvidia-driver/nvidia-driver.mk:$(eval $(kernel-module)) package/ocf-linux/ocf-linux.mk:$(eval $(kernel-module)) package/on2-8170-modules/on2-8170-modules.mk:$(eval $(kernel-module)) package/owl-linux/owl-linux.mk:$(eval $(kernel-module)) package/pkg-kernel-module.mk:# $(eval $(kernel-module)) package/pkg-kernel-module.mk:# $(eval $(kernel-module)) package/rtl8188eu/rtl8188eu.mk:$(eval $(kernel-module)) package/rtl8821au/rtl8821au.mk:$(eval $(kernel-module)) package/simicsfs/simicsfs.mk:$(eval $(kernel-module)) package/sysdig/sysdig.mk:$(eval $(kernel-module)) 

是的,我想我可以写一个冗长的回复,但我只是复制Buildroot手册。 因此,让我们尊重勇敢的开发人员,他们已经编写了如此简洁的文档和如此简洁的代码(Buildroot核心非常干净,每个软件包都经过了广泛的审核,所以它们通常写得非常好)。

完全自动化的树外QEMU示例

https://github.com/cirosantilli/linux-kernel-module-cheat

来源树:

  • buildroot/ :Buildroot 2017.02子模块
  • kernel_module/ :带有一些模块的外部包
    • Config.in
    • external.mk
    • Makefile
    • hello.c :hello world模块

kernel_module / Config.in:

 config BR2_PACKAGE_KERNEL_MODULE bool "kernel_module" depends on BR2_LINUX_KERNEL help Linux Kernel Module Cheat. 

kernel_module / external.mk:

 KERNEL_MODULE_VERSION = 1.0 KERNEL_MODULE_SITE = $(BR2_EXTERNAL_KERNEL_MODULE_PATH) KERNEL_MODULE_SITE_METHOD = local $(eval $(kernel-module)) $(eval $(generic-package)) 

kernel_module / Makefile文件:

 obj-m += $(addsuffix .o, $(notdir $(basename $(wildcard $(BR2_EXTERNAL_KERNEL_MODULE_PATH)/*.c)))) ccflags-y := -DDEBUG -g -std=gnu99 -Wno-declaration-after-statement .PHONY: all clean all: $(MAKE) -C '$(LINUX_DIR)' M='$(PWD)' modules clean: $(MAKE) -C '$(LINUX_DIR)' M='$(PWD)' clean 

kernel_module / hello.c中:

 #include  #include  MODULE_LICENSE("GPL"); static int myinit(void) { printk(KERN_INFO "hello init\n"); return 0; } static void myexit(void) { printk(KERN_INFO "hello exit\n"); } module_init(myinit) module_exit(myexit) 

用法:

 cd buildroot make BR2_EXTERNAL="$(pwd)/../kernel_module" qemu_x86_64_defconfig echo 'BR2_PACKAGE_KERNEL_MODULE=y' >> .config make BR2_JLEVEL="$(($(nproc) - 2))" all qemu-system-x86_64 -M pc -kernel output/images/bzImage -drive file=output/images/rootfs.ext2,if=virtio,format=raw -append root=/dev/vda -net nic,model=virtio -net user 

QEMU打开,然后运行:

 root modprobe hello modprobe -r hello 

dmesg显示:

 hello init hello exit 

关键是external.mk $(eval $(kernel-module)) ,它为我们设置了一切,并安装modprobe将找到它们的模块( /lib/modules/*/extra/hello.ko ),包括模块间依赖关系的modules.dep : 如何从另一个模块调用导出的内核模块函数?

如何GDB步骤调试内核模块: 如何使用QEMU调试Linux内核模块?

要在启动时自动加载模块,请使用BR2_ROOTFS_OVERLAY="../rootfs_overlay"和执行rootfs_overlay/etc/init.d/S99modules文件。

树内例子: https : //github.com/cirosantilli/buildroot/tree/9580078b98f885ca94e4dfc896265a8a491f6ae1它不太干净,但也有效。

在Ubuntu 16.04主机上测试。