7.1. 内核头文件

如果你正在编译内核模块或类似的代码,你将需要 Linux 内核头文件。这些头文件包含Linux内核的各种常量定义、宏定义、函数接口定义和数据结构定义,是完成内核模块代码编译所必须的依赖。

7.1.1. 安装

你可以通过以下命令安装旭日X3派的内核头文件。

sudo apt install hobot-linux-headers

命令运行成功后,内核头文件会被安装到/usr/src/linux-headers-4.14.87目录下

root@ubuntu:~# ls /usr/src/linux-headers-4.14.87/
arch   certs   Documentation  firmware  include  ipc      kernel  Makefile  Module.symvers  samples  security  System.map  usr
block  crypto  drivers        fs        init     Kconfig  lib     mm        net             scripts  sound     tools       virt

7.1.2. 使用示例

我们用一个简单的 Hello World 内核模块的开发介绍如果使用内核头文件。步骤概要如下:

  • 准备程序代码

  • 编写Makefile,完成驱动模块的编译

  • 对驱动模块进行签名

  • 测试加载、卸载模块

  • (可选)配置开机自动加载

7.1.2.1. 编写Hello World驱动程序

打开你熟悉的编辑器(比如VIM),创建文件 hello.c,输入下面的内容:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("xxx.xxx");
MODULE_DESCRIPTION("Hello World");

static int __init hello_init(void)
{
    printk(KERN_ERR "Hello, World!\n");
    return 0;
}
static void __exit hello_exit(void)
{
    printk(KERN_EMERG "Goodbye, World!\n");
}

module_init(hello_init);
module_exit(hello_exit);

模块加载时打印Hello, World!, 模块卸载时打印Goodbye, World!

7.1.2.2. 编写Makefile

打开你熟悉的编辑器(比如VIM),创建文件 Makefile,输入下面的内容:

ifneq ($(KERNELRELEASE),)
    obj-m := hello.o
else
    PWD=$(shell pwd)
    KDIR := /usr/src/linux-headers-4.14.87

all:
    make -C $(KDIR) M=$(PWD) modules
clean:
    rm -rf *.ko *.o *.mod.o *.mod.c *.symvers  modul* .*.ko.cmd .*.o.cmd .tmp_versions
endif
  • PWD指定源码路径,即hello.c的路径。

  • KDIR指定内核源码路径。

  • KERNELRELEASE是在内核源码的顶层Makefile里定义的变量。

保存Makefile后,执行make命令完成模块的编译,生成hello.ko文件。

root@ubuntu:~# make 
make  -C /usr/src/linux-headers-4.14.87 M=/root modules
make[1]: Entering directory '/usr/src/linux-headers-4.14.87'
  CC [M]  /root/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /root/hello.mod.o
  LD [M]  /root/hello.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.14.87'

7.1.2.3. 驱动模块签名

编译好的驱动模块文件,需要进行签名后才能加载到旭日X3派的内核里,命令如下:

root@ubuntu:~# hobot-sign-file hello.ko
Sign Kernel Module File Done.

如果不对驱动模块文件签名而直接加载,则会报以下错误:

insmod: ERROR: could not insert module hello.ko: Required key not available

7.1.2.4. 加载驱动模块

加载ko:insmod hello.ko

root@ubuntu:~# insmod hello.ko
[ 3104.480703] Hello, World!

卸载ko:rmmod hello

root@ubuntu:~# rmmod hello 
[ 3136.909409] Goodbye, World!

查看ko是否加载:lsmod | grep hello

root@ubuntu:~# lsmod | grep hello
hello                  16384  0

执行命令dmesg查看内核打印信息如下:

[ 3104.480361] hello: loading out-of-tree module taints kernel.
[ 3104.480703] Hello, World!
[ 3136.909409] Goodbye, World!

7.1.2.5. 配置开机自动加载驱动

如果想要自定义的驱动模块在开机时自动加载,请按照以下步骤进行配置:

拷贝hello.ko/lib/modules/4.14.87 目录,命令如下:

sudo cp -f hello.ko /lib/modules/4.14.87/

执行depmod命令更新模块的依赖关系:

sudo depmod

最后在 /lib/modules-load.d 目录下新建一个conf扩展名的配置文件,例如 hello.conf,在配置文件里添加需要自动加载的模块名(模块名不需要.ko 扩展名),例如需要自动加载hello.ko,就写一行hello,如果有多个模块需要加载,一个配置文件可以添加多个自加载模块,一行一个模块名,可以通过以下命令简便的完成配置文件的新建和配置:

sudo echo hello > /lib/modules-load.d/hello.conf