我们在学习C语言或着其他语言的时候第一个程序都是打印hello world,所以我们今天学习驱动程序的开发也是使用hello world作为我们的第一个程序。
在开始编程之前我们需要我们需要搜先准备好我们的编程环境和一些环境的安装,下面根据步骤我们一起开始编写我们的第一个驱动程序。
我们使用下面的命令查看我们是否有内核头文件,若和我的显示效果相同,则说明你的电脑是存在内核头文件的,则进行下一步,若不存在该文件,请大家自行百度查看如何下载内核头文件。
apt-cache search linux-headers-$(uname -r)

使用下面的命令进行安装内核头文件,具体代码及执行效果如下图所示:
sudo apt-get install linux-headers-$(uname -r)

在写第一个驱动程序前,我们需要明白系统调用应用层是如何调用硬件设备的?
应用层通过 open 函数调用C库(glibc),通过swi指令发生异常陷入内核态,根据异常的原因调用处理函数sys_open,然后调用drv_open,此时就是我们的驱动程序了。

下面是我们写的第一个程序,大家可以将程序复制到自己的Linux下看看能不能正确编译,如果不能正确编译则说明你的驱动环境有问题,需要重新配置我们的驱动环境。
hello.c文件
#include <linux/module.h>
#include <linux/init.h>
/*把上述的结构体告诉内核,所以要注册*/
int __init hello_init(void)
{
printk("hello_init!\n");
return 0;
}
void __exit hello_exit(void)
{
printk("hello_exit!\n");
}
/*修饰*/
module_init(hello_init);
module_exit(hello_exit);
/*许可证*/
MODULE_LICENSE("GPL");
其中语句printk 是用于打印的函数,这点和我们在学习C语言过程中使用的printf很像,但是又有所不同。
语句module_init(hello_init) 用于定义驱动的入口函数为函数hello_init ,语句module_exit(hello_exit)用于定义驱动的出口函数为函数hello_exit
Makefile文件:
KVERSION = $(shell uname -r)
KERN_DIR = /lib/modules/$(KVERSION)/build
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += hello.o
KVERSION = $(shell uname -r) 读取当前操作系统名称并传递给变量KVERSION,用于下面KERN_DIR路径;KERN_DIR为Linux内核的源码树目录;obj-m += hello.o指定当前目录要生成的目标模块,然后modules目标指向obj-m变量中设定的模块;我们对驱动程序的编译使用make指令及进行,如下图所示:

我们装载驱动程序需要使用sudo insmod + 文件名.ko 指令进行
.ko文件是我们make出来的文件,如下图所示:

指令运行过程截图:

我们在装载完驱动程序后是不会直接进行打印的,我们可以通过lsmod 来查看我们的装载是否成功,执行结果如下图所示:

我们使用sudo rmmod hello+驱动名 可以对已装载的驱动进行卸载,具体如下图所示:

我们使用sudo dmesg 对打印信息进行显示,具体运行结果如下:

Dmesg 用于显示内核环形缓冲区的内容,内核在其中存储各种消息。在运行 dmesg时,它会显示大量信息。dmesg的输出通常通过 less 或 grep 查看,这使得查找要检查的信息更加容易。
上面就是我们运行第一个驱动程序的全部过程,如果你在编写过程中遇到什么问题,欢迎在评论区留言,大家一起交流。