目录
向Linux内核添加新功能的静态加载与动态加载
开发环境:
一、静态加载法
1、新功能源码与Linux内核源码在同一个目录结构下
2、给新功能代码配置Kconfig
3、给新功能代码改写Makefile
5、使用以下指令重新编译内核
6、使用以下命令将生成的uImage内核镜像文件拷贝到tftp的工作目录下
7、启动开发板观察串口终端中的打印信息即可
二、动态加载法
新功能源码与Linux内核源码在同一个目录结构下(大部分配置流程和静态加载时类似)
新功能源码与Linux内核源码不在同一目录结构下
向Linux内核添加新功能的静态加载与动态加载
开发环境:
Ubuntu18.04
在进行linux驱动开发时,当我们想要向linux内核添加一些新功能时,一般可以采用静态加载和动态加载的方法。以下简要介绍下这两种不同的加载方式及一般流程。
一、静态加载法
所谓静态加载法,即将新功能的源码与内核其它代码一起编译进uImage内核镜像文件内。
内核源码顶层目录:/home/ubuntu/linux-3.14 新功能源码文件名:myhello.c 新功能源码路径和linux内核字符设备驱动的路径:/home/ubuntu/linux-3.14/drivers/char/
1、新功能源码与Linux内核源码在同一个目录结构下
myhello.c文件内容如下:
#include <linux/module.h> #include <linux/kernel.h> int __init myhello_init(void) { printk("#####################################################\n"); printk("#####################################################\n"); printk("#####################################################\n"); printk("#####################################################\n"); printk("myhello is running\n"); printk("#####################################################\n"); printk("#####################################################\n"); printk("#####################################################\n"); printk("#####################################################\n"); return 0; } void __exit myhello_exit(void) { printk("myhello will exit\n"); } MODULE_LICENSE("GPL"); module_init(myhello_init); module_exit(myhello_exit);
2、给新功能代码配置Kconfig
#进入myhello.c所在目录 cd ~/linux-3.14/drivers/char vim Kconfig 在配置文件中添加如下内容: config MY_HELLO tristate "This is a hello test" help This is a test for kernel new function
3、给新功能代码改写Makefile
#进入myhello.c所在目录 cd ~/linux-3.14/drivers/char vim Makefile #使用obj指定要编译的对应的.o文件(前面的源文件是.c文件,这里是.c文件所对应的.o文件) obj-$(CONFIG_MY_HELLO) += myhello.o
4、使用make menuconfig 在配置界面里将新功能对应的那项选择成<*>
cd ~/linux-3.14 make menuconfig 注意: 如果使用make menuconfig时出错,一般是以下两个原因: 1. libncurses5-dev没有安装 可以使用以下命令进行安装: sudo apt-get update sudo apt-get install libncurses5-dev 2. 命令行界面太小(太矮或太窄或字体太大了)
首先、在界面下找到Device Drivers(设备驱动)。如下图所示:
然后、找到Character devices(字符设备驱动)。如下图所示:
接着、可以找到我们之前添加的源文件myhello.c的配置信息。在对应的配置项前面设置为<*>,如下图所示:
最后,使用左右键选择Exit一步一步的退出,出现如下界面时选择Yes保存配置即可。
5、使用以下指令重新编译内核
make uImage(这里需要提前配置好所使用的交叉编译器,编译出在ARM平台使用的内核镜像文件)
6、使用以下命令将生成的uImage内核镜像文件拷贝到tftp的工作目录下
使用以下命令将生成的uImage内核镜像文件拷贝到tftp的工作目录下,我这里是/tftpboot。 cp arch/arm/boot/uImage /tftpboot
7、启动开发板观察串口终端中的打印信息即可
如下图所示,可以看到我们之前程序源码中的打印信息。这就说明我们向内核中新添加的功能正常运行了。
二、动态加载法
所谓动态加载法,即新功能源码与内核其它源码不一起编译,而是独立编译成内核的插件(被称为内核模块)文件.ko。
动态加载法又可以分为两种情况: 1、新功能源码与Linux内核源码在同一个目录结构下。 2、新功能源码与Linux内核源码不在同一个目录结构下。
新功能源码与Linux内核源码在同一个目录结构下(大部分配置流程和静态加载时类似)
1. 给新功能源码配置Kconfig 2. 给新功能代码改写Makefile,Makefile文件如下: #====================================================================== ifeq ($(KERNELRELEASE),) ifeq ($(ARCH),arm) KERNELDIR ?= linux内核源码顶层目录的绝对路径 ROOTFS ?= 网络文件系统顶层目录的绝对路径 else KERNELDIR ?= /lib/modules/$(shell uname -r)/build endif PWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules INSTALL_MOD_PATH=$(ROOTFS) modules_install clean: rm -rf *.o *.ko .*.cmd *.mod.* modules.order Module.symvers .tmp_versions else obj-m += myhello.o endif #注意: #Makefile里如果没有配置交叉编译工具链,可以在~/.bashrc中进行配置,或者使用export等命令临时配置。 #obj-m用来指定模块名,注意模块名加.o而不是.ko。 #一个目录下的Makefile可以编译多个模块: #添加:obj-m += 下一个模块名.o #====================================================================== 3. 使用make menuconfig,在配置界面里将新功能对应的那项选择成<M> 4. 使用make uImage重新编译内核 5. 将生成的uImage内核镜像文件拷贝到tftp的工作目录下 cp arch/arm/boot/uImage /tftpboot 6. 使用make modules命令重新编译内核模块(注意此命令执行前,要保证开发板的内核源码已经被编译) make modules命令会在新功能源码的同级目录下生成相应的同名.ko文件
新功能源码与Linux内核源码不在同一目录结构下
内核源码顶层目录:/home/ubuntu/linux-3.14 新功能源码文件名:myhello.c linux内核字符设备驱动的路径:/home/ubuntu/linux-3.14/drivers/char/ 新功能源码路径:/home/ubuntu/mydrivercode
1. cd ~ 2. mkdir mydrivercode 3. cd mydrivercode 4. cp ~/linux-3.14/drivers/char/myhello.c . //拷贝之前的myhello测试程序源码 5. vim Makefile 6. make ARCH=arm (生成的ko文件适用于linux开发板,注意此命令执行前,开发板的内核源码已被编译)
注意: 1、Makefile里如果没有配置交叉编译工具链,可以在~/.bashrc中进行配置,或者使用export等命令临时配置。 2、使用file命令可以查看编译出的ko文件适用于哪种平台,用法: file ko文件 输出结果带x86字样的适用于主机ubuntu,带ARM字样的适用于ARM linux开发板。
7、在ARM开发板下加载驱动模块 7.1首先将生成的.ko文件拷贝到网络文件系统nfs的工作目录下 cp xxx/xxx.ko 网络文件系统nfs的工作目录 7.2然后在开发板上使用mount命令挂载ubuntu主机上的网络文件系统 7.3接着使用mobaxterm等软件采用串口连接的方式连接开发板的串口,在其终端下输入: insmod ./xxx.ko #将内核模块插入正在执行的内核中运行 ----- 相当于安装插件 lsmod #查看已被插入的内核模块有哪些 rmmod xxx #将已被插入的内核模块从内核中移除 ----- 相当于卸载插件 内核随时打印信息,我们可以在串口终端界面看到打印信息。
完结。。。