1 动态加载法
即新功能源码与内核其它源码不一起编译,而是独立编译成内核的插件(被称为内核模块)文件.ko
1.1 新功能源码与Linux内核源码在同一目录结构下时
给新功能代码配置Kconfig(模块代码与上一级相同)
给新功能代码改写Makefile
make menuconfig 界面里将新功能对应的那项选择成<M>
make uImage
cp arch/arm/boot/uImage /tftpboot(复制uImage到tftp服务器目录)
make modules
make modules会在新功能源码的同级目录下生成相应的同名.ko文件(生成的ko文件只适用于开发板linux)
注意此命令执行前,开发板的内核源码已被编译
1.2 新功能源码与Linux内核源码不在同一目录结构下时
1.2.1 创建内核新功能源码和目录
cd ~/fs4412
mkdir mydrivercode //后续驱动源码都放这个目录
cd mydrivercode
cp ../linux-3.14/drivers/char/myhello.c . //复制模块源码
1.2.2 编写makefile(注意路径)
vim Makefile
内容:
ifeq ($(KERNELRELEASE),)
ifeq ($(ARCH),arm)
KERNELDIR ?= /home/linux/fs4412/linux-3.14
ROOTFS ?= /opt/4412/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
这是一个 Linux 内核模块的 Makefile 文件,其中包含了模块编译、安装和清理等规则。
如果当前的 KERNELRELEASE 变量没有被定义(即在命令行中没有指定),那么它会进入第一个 ifeq 块中。根据 ARCH 变量的值,选择对应的内核源代码目录和根文件系统路径。然后通过调用 make 命令进入内核源代码目录,使用 M 参数指定当前模块所在的路径,执行 modules 规则编译模块,并生成 .ko 文件。接着,执行 modules_install 规则,将编译好的模块拷贝到 $(ROOTFS) 目录中,以便在根文件系统启动时加载使用。
如果 KERNELRELEASE 变量已经被定义,则说明当前是在内核源代码目录中进行编译,直接将 myhello.c 文件编译成 myhello.ko 模块,并添加到 obj-m 变量中。
最后,如果需要清理当前目录下的所有编译生成的文件,可以执行 clean 规则。
1.2.3 生成的ko文件
make (生成的ko文件适用于主机ubuntu linux)
make ARCH=arm (生成的ko文件适用于开发板linux,注意此命令执行前,开发板的内核源码已被编译)
#file命令可以查看指定ko文件适用于哪种平台,用法:
file ko文件
#结果带x86字样的适用于主机ubuntu linux,带arm字样的适用于开发板linux
1.3 主机ubuntu下使用ko文件
sudo insmod ./???.ko #此处为内核模块文件名,将内核模块插入正在执行的内核中运行 ----- 相当于安装插件
lsmod #查看已被插入的内核模块有哪些,显示的是插入内核后的模块名
sudo rmmod ??? #,此处为插入内核后的模块名,此时将已被插入的内核模块从内核中移除 ----- 相当于卸载插件
sudo dmesg -C #清除内核已打印的信息
dmesg #查看内核的打印信息
1.4 开发板Linux下使用ko文件
#先将生成的ko文件拷贝到/opt/4412/rootfs目录下:
cp ????/???.ko /opt/4412/rootfs
#在串口终端界面开发板Linux命令行下执行
insmod ./???.ko #将内核模块插入正在执行的内核中运行 ----- 相当于安装插件
lsmod #查看已被插入的内核模块有哪些
rmmod ??? #将已被插入的内核模块从内核中移除 ----- 相当于卸载插件
内核随时打印信息,我们可以在串口终端界面随时看到打印信息,不需要dmesg命令查看打印信息