一些重要的宏和数据结构
这两个宏用于为Kernel标识模块初始化和模块清除阶段的函数
__init:会在初始化内核模块后被丢弃,将内存分配给其他用途
__exit:如果模块未被配置为可卸载模块的情况下会直接被丢弃
很重要的内核API定义头文件:#include <linux/sched.h>
,在该头文件中可以获取到指向task_struct的指针current来获取到当前执行的进程。
可以通过:
current->pid
:访问当前进程的ID
current->comm
:访问当前进程的命令名
为驱动传递参数
驱动参数
在安装驱动的时候可以为驱动传递参数,需要包含头文件#include <linux/moduleparam.h>
主要通过以下的宏进行:
module_param(variable, type, perm)
例如可以通过module_param(howmany,int,S_IRUGO)
定义一个int类型的howmany参数
module_param支持:bool、invbool、charp、int、long、short、uint、ulong、ushort
所以可以编写如下代码来接受安装驱动程序时候的参数:
#include <linux/module.h>
#include <linux/init.h>
#include <asm/current.h>
#include <linux/sched.h>
static char *whom = "world";
static int howmany = 1;
module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO);
static int __init test_init(void){
printk(KERN_ALERT "The process is \"%s\" (pid %i)\n", current->comm, current->pid);
for(int i = 0; i < howmany; i++){
printk(KERN_ALERT "%s", whom);
}
return 0;
}
static void __exit test_exit(void){
printk(KERN_ALERT "Goodbye Kernel\n");
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
module_param中perm字段用来控制谁能够访问sysfs中对模块参数的描述,如果perm被设置为0,就不会有对应的sysfs的入口项。如果对应S_IRUGO代表任何人都可以读取该参数但是不能修改
我们可以使用sudo insmod hello.ko howmany=10 whom="Mom"
来带着参数安装该内核模块,之后在dmesg中可以看到Mom被输出了10次
因为我们将perm字段设置为了任何人可以读取参数,那么我们可以在sysfs中查看到当前内核模块的参数以及现在的值,如果perm被设置为了可写,那么可以直接操作sysfs中的项来更改内核模块中的数据:
环境配置的问题
直接复制上述代码到vscode中会报KBUILD_MODULE找不到定义的错误,这个变量是在Makefile的时候才生成的,可以在define数组中加入MODULE定义即可修复该问题
还有个问题是current指针无法自动提示task_struct的成员,这里可以设置配置中的browse来开启代码提示:
"browse": {
"path": [
"${workspaceFolder}",
"/usr/src/linux/include",
"/usr/src/linux/mm",
"/usr/src/linux/fs",
"/usr/src/linux/kernel"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
此问题可以在github的issue中找到:https://github.com/microsoft/vscode-cpptools/issues/5588
完整的config文件:
{
"configurations": [
{
"name": "Linux Kernel Module",
"includePath": [
"${workspaceFolder}/**",
"/usr/src/linux/include",
"/usr/src/linux/include/uapi",
"/usr/src/linux/include/generated",
"/usr/src/linux/arch/x86/include",
"/usr/src/linux/arch/x86/include/uapi",
"/usr/src/linux/arch/x86/include/generated"
],
"defines": [
"KBUILD_MODNAME=\"dummyname\"",
"__GNUC__",
"__KERNEL__",
"MODULE"
],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64",
"configurationProvider": "ms-vscode.makefile-tools",
"browse": {
"path": [
"${workspaceFolder}",
"/usr/src/linux/include",
"/usr/src/linux/mm",
"/usr/src/linux/fs",
"/usr/src/linux/kernel"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
],
"version": 4
}