我们首先从hello world 开始编写一个驱动模块
既然说模快,肯定有非模块,非模块就是直接编译进内核。
模块具有这样的特点:
模块不会被编译进内核,从而减少了内核image的大小
内核加载后,与内核中其他部分一样
废话不多说,先上代码
hello_world.c
#include
#include
MODULE_LICENSE("GPL v2"); //模块许可证声明,如果不声明,加载模块时,会出现内核被污染(kernel tainted)的警告
MODULE_AUTHOR("xl"); //声明模块的作者
MODULE_DESCRIPTION("a simple hello world module");//模块的描述
static char *name = "hello world";
module_param(name,charp,S_IRUGO); //加载模块时输入的参数
static int __init hello_init(void)
{
printk("module init\n");
printk("parameter name is : %s\n",name);
return 0;
}
module_init(hello_init);
static void __exit hello_exit(void)
{
printk("module exit\n");
}
module_exit(hello_exit);
int add(int a, int b)
{
return a+b;
}
EXPORT_SYMBOL(add);
Makefile
obj-m:=hello_world.o
KDIR:= /lib/modules/4.4.0-171-generic/build //内核目录
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order
当前目录下的文件如下:
root@xl-virtual-machine:/home/xl/linux_codes# ls
hello_world.c Makefile
输入make命令进行编译,生成文件如下所示
root@xl-virtual-machine:/home/xl/linux_codes# make
make -C /lib/modules/4.4.0-171-generic/build M=/home/xl/linux_codes modules
make[1]: Entering directory '/usr/src/linux-headers-4.4.0-171-generic'
CC [M] /home/xl/linux_codes/hello_world.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/xl/linux_codes/hello_world.mod.o
LD [M] /home/xl/linux_codes/hello_world.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.4.0-171-generic'
root@xl-virtual-machine:/home/xl/linux_codes# ls
hello_world.c hello_world.mod.c hello_world.o modules.order
hello_world.ko hello_world.mod.o Makefile Module.symvers
root@xl-virtual-machine:/home/xl/linux_codes#
hello_world.ko 为生成的驱动文件,使用insmod hello_world.ko命令加载驱动,使用dmesg -c查看输出
root@xl-virtual-machine:/home/xl/linux_codes# insmod hello_world.ko
root@xl-virtual-machine:/home/xl/linux_codes# dmesg -c
[28411.480284] module init
[28411.480293] parameter name is : hello world
root@xl-virtual-machine:/home/xl/linux_codes#
卸载驱动:rmmod hello_world
root@xl-virtual-machine:/home/xl/linux_codes# rmmod hello_world
root@xl-virtual-machine:/home/xl/linux_codes# dmesg -c
[31809.006710] module exit
扩展:
__init和__exit的作用是告诉编译器将这些函数或者数据放入相应的代码段。
使用了__init和__exit,则代码使用的内存会在使用后被释放掉,以节省系统开销。
使用modinfo hello_world.ko查看模块信息,包括作者、说明等
root@xl-virtual-machine:/home/xl/linux_codes# modinfo hello_world.ko
filename: /home/xl/linux_codes/hello_world.ko
description: a simple hello world module
author: xl
license: GPL v2
srcversion: 3327DF89233436F0B2F297F
depends:
retpoline: Y
vermagic: 4.4.0-171-generic SMP mod_unload modversions
parm: name:charp
加载模块时输入参数:insmod hello_world.ko name=xl
如下所示参数name的值变为xl.
root@xl-virtual-machine:/home/xl/linux_codes# insmod hello_world.ko name=xl
root@xl-virtual-machine:/home/xl/linux_codes# dmesg -c
[32640.753793] module init
[32640.753806] parameter name is : xl
导出符号
EXPORT_SYMBOL()导出符号到内核符号表,导出的符号可以被其它模块使用,其它模块使用时只需要声明一下即可。
在/proc/kallsyms中记录了符号以及符号所在的内存地址。
root@xl-virtual-machine:/home/xl/linux_codes# grep hello_add /proc/kallsyms
ffffffffc0427087 r __kstrtab_hello_add [hello_world]
ffffffffc0427040 r __kcrctab_hello_add [hello_world]
ffffffffc0427030 r __ksymtab_hello_add [hello_world]
ffffffffc0426000 T hello_add [hello_world]