嵌入式Linux|设备驱动开发实验教程(3)_在Ubuntu 18.04环境下编写一个简单的内核模块

内核模块定义
模块是具有独立功能的程序,可以单独编译,但是不能单独运行。模块在运行时,会被链接到内核,作为内核的一部分在内核空间运行。模块通常由一组函数和数据结构组成,用来实现一种文件系统、驱动程序或其他内核上层的功能。

内核模块基本原理
Linux 内核模块(LKM)是一些在启动的操作系统内核需要时可以载入内核执行的代码块,不需要时由操作系统卸载。它们扩展了操作系统内核功能却不需要重新编译内核、启动系统。如果没有内核模块,就不得不反复编译生成操作系统的内核镜像来加入新功能,当附加的功能很多时,还会使内核变得臃肿。一个Linux 内核模块主要由以下几个部分组成:
(1) 模块加载函数(必须):当通过insmod 或modprobe 命令加载内核模块时,模块的加载函数会自动被内核执行,完成本模块相关初始化工作。
(2) 模块卸载函数(必须):当通过rmmod 命令卸载模块时,模块的卸载函数会自动被内核执行,完成与模块加载函数相反的功能。
(3) 模块许可证声明(必须):模块许可证(LICENCE)声明描述内核模块的许可权限,如果不声明LICENCE,模块被加载时将收到内核被污染的警告。大多数情况下,内核模块应遵循GPL 兼容许可权。Linux2.6 内核模块最常见的是以MODULE_LICENSE(“Dual BSD/GPL”)语句声明模块采用BSD/GPL 双LICENSE。
(4) 模块参数(可选):模块参数是模块被加载的时候可以被传递给他的值,它本身对应模块内部的全局变量。
(5) 模块导出符号(可选):内核模块可以导出符号(symbol,对应于函数或变量),这样其他模块可以使用本模块中的变量或函数。
(6) 模块作者等信息声明(可选)。
一个内核模块至少包含两个函数,模块被加载时执行的初始化函数init_module()和模块被卸载时执行的结束函数cleanup_module()。在最新内核稳定版本2.6 中,两个函数可以起任意的名字,通过宏module_init()和module_exit()注册调用要编译内核模块,把代码嵌进内核空间,首先要获取内核源代码,且版本必需与当前正在运行的版本一致。

hello.c代码清单如下:

#include #include #includestatic int __init lkp_init(void) { printk("<0>" "Hello World from the kernel space...\n"); return 0; }static void __exit lkp_cleanup(void) { printk("<0>" "Good Bye World! leaving kernel space...\n"); }module_init(lkp_init); // 注册模块 module_exit(lkp_cleanup); // 注销模块 MODULE_LICENSE("GPL"); //告诉内核该模块具有GNU公共许可证

【嵌入式Linux|设备驱动开发实验教程(3)_在Ubuntu 18.04环境下编写一个简单的内核模块】
Makefile代码清单如下:
# Makefile 4.0 obj-m := hello.o CURRENT_PATH := $(shell pwd) LINUX_KERNEL := $(shell uname -r) LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL)all: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules clean: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean


编译:执行make命令,如下图。
嵌入式Linux|设备驱动开发实验教程(3)_在Ubuntu 18.04环境下编写一个简单的内核模块
文章图片


加载模块: insmod hello.ko
卸载模块: rmmod hello
模块加载、卸载过程中并未输出printk信息,如下所示:
嵌入式Linux|设备驱动开发实验教程(3)_在Ubuntu 18.04环境下编写一个简单的内核模块
文章图片


要查看printk打印的信息,可执行命令: cat /var/log/syslog | grep Hello
cat /var/log/syslog | grep Good
grep的信息要与hello.c中printk输出的信息对应。
嵌入式Linux|设备驱动开发实验教程(3)_在Ubuntu 18.04环境下编写一个简单的内核模块
文章图片

嵌入式Linux|设备驱动开发实验教程(3)_在Ubuntu 18.04环境下编写一个简单的内核模块
文章图片


编程实例参考:
编写一个简单的内核模块程序Hello World!https://blog.csdn.net/sh21_/article/details/60878812
在Ubuntu 18.04环境下编写一个简单的内核模块https://blog.csdn.net/song_lee/article/details/82995312

    推荐阅读