Heng30的博客
搜索 分类 关于 订阅

如何给Linux内核驱动传递参数?

2025-02-17

在写函数的时候,为了控制内部的运行逻辑或者对内部进行初始化,一般都会给函数传入参数。同样的为了控制内核驱动的行为,我们也希望在驱动加载的时候给它传入初始化参数。通过不同的参数达到不同的初始状态,提高内核驱动的灵活性。

内核驱动模块参数支持的类型:

  • 常用类型:bool int long short uint ulong ushort
  • invbool一个布尔型. 颠倒了值, 所以真值变成false, 反之亦然.
  • charp一个字符指针值. 内存为用户提供的字串分配, 指针因此设置.

下面分别定义了三个不同类型的参数:

static char *whom = "world";
static int howmany = 1;
static int arr[3];

module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO);
module_param_array(arr, int, NULL, S_IRUGO);

module_param宏将变量参数关联起来。第三个参数是设置参数权限。在内核中的定义如下:

#define S_IRWXUGO	(S_IRWXU|S_IRWXG|S_IRWXO)
#define S_IALLUGO	(S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
#define S_IRUGO		(S_IRUSR|S_IRGRP|S_IROTH)
#define S_IWUGO		(S_IWUSR|S_IWGRP|S_IWOTH)
#define S_IXUGO		(S_IXUSR|S_IXGRP|S_IXOTH)
  • S_IRWXUGO: 表示用户(User)、组(Group)和其他用户(Other)的所有权限(读、写、执行)。

    • S_IRWXU:用户(User)的读、写、执行权限。
    • S_IRWXG:组(Group)的读、写、执行权限。
    • S_IRWXO:其他用户(Other)的读、写、执行权限。
  • S_IALLUGO: 表示特殊权限位和用户、组、其他用户的所有权限。

    • S_ISUID:设置用户ID(SUID)位,允许用户以文件所有者的权限执行文件。
    • S_ISGID:设置组ID(SGID)位,允许用户以文件所属组的权限执行文件,或在目录中创建的文件继承目录的组ID。
    • S_ISVTX:粘滞位(Sticky bit),通常用于目录,允许只有文件所有者或root用户才能删除或重命名文件。
    • S_IRWXUGO:用户、组和其他用户的所有权限
  • S_IRUGO: 表示用户、组和其他用户都拥有读权限。

    • S_IRUSR:用户(User)的读权限。
    • S_IRGRP:组(Group)的读权限。
    • S_IROTH:其他用户(Other)的读权限。
  • S_IWUGO: 表示用户、组和其他用户都拥有写权限。

    • S_IWUSR:用户(User)的写权限。
    • S_IWGRP:组(Group)的写权限。
    • S_IWOTH:其他用户(Other)的写权限。
  • S_IXUGO: 表示用户、组和其他用户都拥有执行权限。

    • S_IXUSR:用户(User)的执行权限。
    • S_IXGRP:组(Group)的执行权限。
    • S_IXOTH:其他用户(Other)的执行权限。

示例

// parameters.c

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

static char *whom = "world";
static int howmany = 1;
static int arr[3];
module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO);
module_param_array(arr, int, NULL, S_IRUGO);

static int __init parameters_init(void) {
    for (int i = 0; i < howmany; i++) {
        printk(KERN_INFO "hi, %s\n", whom);
    }

    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
        printk(KERN_INFO "arr[%d] = %d\n", i, arr[i]);
    }

    return 0;
}

static void __exit parameters_exit(void) {
    printk(KERN_INFO "Goodbye, parameters module!\n");
}

module_init(parameters_init);
module_exit(parameters_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("heng30");
MODULE_VERSION("v0.0.1");
MODULE_DESCRIPTION("A simple parameters kernel module");

编译脚本

#!/bin/sh

arch = x86
top-dir = $(shell pwd)
kernel-version = $(shell uname -r)
kernel-dir ?= /lib/modules/$(kernel-version)/build

obj-m = parameters.o
target = parameters.ko

all:
	make -C $(kernel-dir) modules M=$(top-dir)

install:
	insmod $(target) howmany=3 whom="blue" arr=1,2,3

uninstall:
	rmmod $(target)

info:
	modinfo $(target)

clean:
	rm -f *.o *.ko *.mod *.mod.c *.order *.symvers
	make -C $(kernel-dir) clean m=$(top-dir)

dmesg:
	dmesg

传入的参数为howmany=3 whom="blue" arr=1,2,3。运行make install加载驱动。加载成功后,运行make dmesg查看输出信息。