从hello world 开始
前言
linux内核在驱动开发而言主要分为5块:进程管理、内存管理、文件系统、设备控制、网络。内核驱动可以看成一个个模块,也就是.ko文件。但linux内核出于安全考虑并不能将内存管理这类模块卸载。内核开发人员开发的驱动模块可以选择静态编译加载到内核,需要改相应的config文件,有个很大的缺点就是当驱动多的时候内核会变得很大;也可以选择选择动态加载到内核上。方法如下:
#加载模块
insmod example.ko
#卸载模块
rmmod example
#查看模块
lsmod
设备和模块的分类
Linux下一切皆文件,以linux的方式看待设备可区分3种基本设备类型:
- 字符设备 :一个字符(char)设备是一种可以当作一个字节流来存取的设备(如同一个文件),这种驱动一般需要实现open,close(release),read,write系统调用;
- 块设备:如同字符设备,块设备通过/dev目录的文件系统来存取,一般Unix系统只能支持处理IO操作,而linux允许应用程序写一个块设备像字符设备一样,和字符设备的区别仅仅在内核内部管理数据的方式上;
- 网络接口:内核与网络设备驱动间的通讯与字符/块设备驱动所用的完全不同。不用read和write,内核调用和报文传递相关的函数;
也有其他的划分驱动方式,例如USB设备,但是该设备在系统中表现为一个字符设备(USB串口),一个块设备(USB内存读卡器),一个网络设备(一个USB以太网接口)。
Hello World模块
一个模块的最基本的要素为两个:init和exit。其中printk和标准库printf类似,为内核空间打印函数,打印的内容在内核空间的一个环形缓存里面,可以用dmesg命令查看。
#include <linux/init.h>
#include <linux/module.h>
//开源协议
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void) {
printk(KERN_ALERT "hello, linux\n");
return 0;
}
static void hello_exit(void) {
printk(KERN_ALERT "Goodbye cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
编译过程
需要下载内核版本并且编译替代当前版本内核才能进行内核驱动编译,也就是需要提前搭建内核驱动开发环境,之后会写一个内核开发搭建的教程。当前采用内核的版本为:4.9.188,下载地址为:www.kernel.org.
Makefile如下:
obj-m := hello.o
all:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
直接在hello.c所在目录下输入命令:
make
得到hello.ko文件。
加载模块:
insmod hello.ko
卸载模块
rmmod hello
使用dmesg查看,相关结果如下: