Linux编译第一个驱动HelloDriver!

硬件平台信息:

蓝莓派4B+ubuntu22.04-raspi

哪些是linux驱动

当你编撰一个Linux设备驱动程序时linux系统安装,最终会生成一个文件linux内核开发,其文件扩充名为“.ko”,这个文件是可加载内核模块(LoadableKernelModulelinux内核开发,简称LKM)。下边我将详尽解释一下:

可加载内核模块(LKM):

编撰设备驱动:

编译为模块:

加载和卸载模块:

模块的生命周期:

总的来说,.ko文件是Linux设备驱动程序编译生成的二补码文件linux系统编程,它代表了一个可加载的内核模块,容许在运行的Linux系统上动态添加或移除设备驱动功能。

实现最简单的内核驱动程序hello_driver

在系统中任意一个位置创建一个文件夹,用于储存我们的hello_driver.c与Makefile文件

开始编撰hello_driver.c文件

首先须要加入必须的linux系统头文件

   #include 
   #include 
   #include 

内核开发工程师_内核开发包_linux内核开发

“module.h”与”kernel.h”在linux内核模块中是必须的.

“init.h”在module的初始化与退出时须要被调用.

接出来编撰驱动函数,模块的载入与卸载都须要一个函数句柄,所以必需要有_init函数与_exit函数

    static int __init hello_init(void) {
         printk(KERN_INFO "Hello World!n");
         return 0;
    }
    
    static void __exit hello_exit(void) {
        printk(KERN_INFO "Goodbye World!n");
    }
    ```
    由于我们需要将模块是否载入与卸载的信息打印出来, 所以此处用到了printk函数, 即将字符串在kernel log中打印出来, 并且这个log的等级是INFO等级.
    这样, 我们就可以通过dmesg指令来查看模块是否被正确载入或卸载.

内核开发包_linux内核开发_内核开发工程师

4. 最后, 我们要将模块的装载与卸载函数句柄传入 ```c module_init(hello_init); module_exit(hello_exit);

假如这是一个即将的模块,我们也可以为其添加一些模块信息,如下

MODULE_LICENSE("GPL");
MODULE_AUTHOR("NinoC137");
MODULE_DESCRIPTION("Hello World Linux Device Driver");

完整代码如下:

      #include 
      #include 
      #include 
      
      static int __init hello_init(void) {

内核开发包_linux内核开发_内核开发工程师

printk(KERN_INFO "Hello Driver!n"); return 0; } static void __exit hello_exit(void) { printk(KERN_INFO "Goodbye Driver!n"); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("NinoC137"); MODULE_DESCRIPTION("Hello World Linux Device Driver");

开始编撰Makefile文件

这儿我直接在对应linux平台本地环境下开发,所以不须要配置交叉编译的环境,Makefile便可以直接如下写出

obj-m := hello_driver.o
all: hello_driver.c
        sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
        sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

开始编译

在这里插入图片描述

正常情况下不会出现报错.

测试内核驱动程序Hello_Driver

经过昨晚的打算工作,在编译以后,文件夹之中都会有如下文件

在这里插入图片描述

开始测试驱动程序,这儿须要用到insmod与rmmod指令,即装载/卸载内核驱动模块

正常运行下是不会直接复印出信息的,所以我们须要用到sudodmesg命令来查看kernellog

在这里插入图片描述

可见,驱动被正确地装载与卸载了.

我们也可以使用modinfo命令来查看驱动的信息

在这里插入图片描述

在编译驱动晨报错Kernelconfigurationisinvalid

可能会在编译时出现这样的错误

ERROR: Kernel configuration is invalid.
         include/generated/autoconf.h or include/config/auto.conf are missing.
         Run 'make oldconfig && make prepare' on kernel src to fix it.

解决方式:

使用uname-r查看当前的内核版本

步入/lib/modules中对应的内核文件夹的/build文件夹之中

在这里插入图片描述

运行makemenuconfig,不须要做任何更改,点击save后点击load,之后exit退出即可

在这里插入图片描述

重新编译我们的驱动中的makefile文件,此晨报错消失,正常编译.

Tagged:
Author

这篇优质的内容由TA贡献而来

刘遄

《Linux就该这么学》书籍作者,RHCA认证架构师,教育学(计算机专业硕士)。

发表回复