linux设备驱动程序有两种加载方式。一种是直接编译进内核,系统启动的时候自动加载;另一种是编译成模块手动加载进内核。第一种直接编译进内核的方式的优点是不需要每次使用的时候进行加载,缺点是 需要在编译内核的时候一起编译进去,花费时间比较长,一般是驱动程序测试没什么问题之后才会编译进内核。第二中的优点是,可以随时加载和卸载,而且不需要和内核一起编译,可以单独编译,所以花费时间比较少,一般调试驱动的时候用的是这种动态编译的方式。
1.编写可加载模块
hello.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
static int helloworld_init(void)
{
printk("helloworld_init.\n");
return 0;
}
static void helloworld_exit(void)
{
printk("helloworld_exit.\n");
}
module_init(helloworld_init);
module_exit(helloworld_exit);
MODULE_DESCRIPTION("simple module");
MODULE_LICENSE("GPL");
先在ubuntu做测试:
Makefile
obj-m := hello.o
KDIR := /lib/modules/`uname -r`/build
PWD := $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.* *.ko *.symvers *.order
编译后生成hello.ko模块
加载到ubuntu: insmod hello.ko
由于ubuntu下的打印等级不一样,这里加载模块的时候并没有把printk的打印消息打印出来。
可以使用指令查看是否加载成功
lsmod | grep hello
如上图,可以看出模块已经成功加载到系统中
卸载模块: rmmod hello.ko
再次使用lsmod | grep hello查看的时候,会发现模块已经卸载了。
在ARM中加载:
Makefile
obj-m := hello.o
KDIR := /home/vinkim/OrangePiH6/kernel
PWD := $(shell pwd)
default:
make ARCH=arm64 CROSS_COMPILE=/opt/toolchain/gcc-linaro-aarch/bin/aarch64-linux-gnu- -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.* *.ko *.symvers *.order
需要将模块加载到arm中,需要修改KDIR为你的linux内核所在位置,并指定ARCH(芯片架构)和你的CROSS_CONPILE(交叉编译工具链)。编译后即可将生成的hello.ko拷贝到你的arm开发板上进行加载,加载和卸载指令参考上面。