歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

Linux 驅動之模塊參數--Linux設備驅動程序

模塊參數


很多情況下,我們期望通過參數來控制我們的驅動的行為,比如由於系統的不同,而為了保證我們驅動有較好的移植性,我們有時候期望通過傳遞參數來控制我們驅動的行為,這樣不同的系統中,驅動可能有不同的行為控制。

為了滿足這種需求,內核允許對驅動程序指定參數,而這些參數可在加載驅動的過程中動態的改變

參數的來源主要有兩個

使用insmod/modprobe ./xxx.ko時候在命令行後直接給出參數;

modprobe命令裝載模塊時可以從它的配置文件/etc/modprobe.conf文件中讀取參數值

這個宏必須放在任何函數之外,通常實在源文件的頭部

模塊參數傳遞的方式


對於如何向模塊傳遞參數,Linux kernel 提供了一個簡單的框架。其允許驅動程序聲明參數,並且用戶在系統啟動或模塊裝載時為參數指定相應值,在驅動程序裡,參數的用法如同全局變量。

使用下面的宏時需要包含頭文件


module_param(name, type, perm)
module_param_array(name, type, num_point, perm);
module_param_named(name_out, name_in, type, perm);
module_param_string(name, string, len, perm);

參數類型


內核支持的模塊參數類型如下

參數 描述 bool 布爾類型(true/false),關聯的變量類型應該死int intvbool bool的反值,例如賦值位true,但是實際值位false int 整型 long 長整型 short 短整型 uint 無符號整型 ulong 無符號長整形型 ushort 無符號短整型 charp 字符指針類型,內核會為用戶提供的字符串分配內存,並設置相應指針

關於數組類型怎麼傳遞,我們後面會談到

注意

如果我們需要的類型不在上面的清單中,模塊代碼中的鉤子可讓我們來指定這些類型。

具體的細節請參閱moduleparam.h文件。所有的模塊參數都應該給定一個默認值;

insmod只會在用戶明確設定了參數值的情況下才會改變參數的值,模塊可以根據默認值來判斷是否一個顯示給定的值

訪問權限


perm訪問權限與linux文件愛你訪問權限相同的方式管理,

如0644,或使用stat.h中的宏如S_IRUGO表示。

我們鼓勵使用stat.h中存在的定義。這個值用來控制誰能夠訪問sysfs中對模塊參數的表述。
如果制定0表示完全關閉在sysfs中相對應的項,否則的話,模塊參數會在/sys/module中出現,並設置為給定的訪問許可。

如果指定S_IRUGO,則任何人均可讀取該參數,但不能修改
如果指定S_IRUGO | S_IWUSR 則允許root修改該值

注意

如果一個參數通過sysfs而被修改,則如果模塊修改了這個參數的值一樣,但是內核不會以任何方式通知模塊,大多數情況下,我們不應該讓模塊參數是可寫的,除非我們打算檢測這種修改並做出相應的動作。

如果你只有ko文件卻沒有源碼,想知道模塊中到底有哪些模塊參數,不著急,只需要用


modinfo -p ${modulename}

就可以看到個究竟啦。

對於已經加載到內核裡的模塊,如果想改變這些模塊的模塊參數該咋辦呢?簡單,只需要輸入

echo -n ${value} > /sys/module/${modulename}/parameters/${param}

來修改即可。

示例


傳遞全局參數


在模塊裡面, 聲明一個變量(全局變量),用來接收用戶加載模塊時傳遞的參數

module_param(name, type, perm);
參數 描述 name 用來接收參數的變量名 type 參數的數據類型 perm 用於sysfs入口項系的訪問可見性掩碼

示例–傳遞int


這些宏不會聲明變量,因此在使用宏之前,必須聲明變量,典型地用法如下:

static int value = 0;
module_param(value, int, 0644);
MODULE_PARM_DESC(value_int, "Get an value from user...\n");

使用

sudo insmod param.ko value=100 

來進行加載

示例–傳遞charp


static char *string = "gatieme";
module_param(string, charp, 0644);
MODULE_PARM_DESC(string, "Get an string(char *) value from user...\n");

使用

sudo insmod param.ko string="hello" 

在模塊內部變量的名字和加載模塊時傳遞的參數名字不同


前面那種情況下,外部參數的名字和模塊內部的名字必須一致,那麼有沒有其他的綁定方法,可以是我們的參數傳遞更加靈活呢?

使模塊源文件內部的變 量名與外部的參數名有不同的名字,通過module_param_named()定義。

module_param_named(name_out, name_in, type, perm);
參數 描述 name_out 加載模塊時,參數的名字 name_in 模塊內部變量的名字 type 參數類型 perm 訪問權限

使用

static int  value_in = 0;
module_param_named(value_out, value_in, int, 0644);
MODULE_PARM_DESC(value_in, "value_in named var_out...\n");

加載

sudo insmod param.ko value_out=200

傳遞字符串


加載模塊的時候, 傳遞字符串到模塊的一個全局字符數組裡面

module_param_string(name, string, len, perm);
參數 描述 name 在加載模塊時,參數的名字 string 模塊內部的字符數組的名字 len 模塊內部的字符數組的大小 perm 訪問權限
static char buffer[20] = "gatieme";
module_param_string(buffer, buffer, sizeof(buffer), 0644);
MODULE_PARM_DESC(value_charp, "Get an string buffer from user...\n");

傳遞數組


加載模塊的時候, 傳遞參數到模塊的數組中

module_param_array(name, type, num_point, perm);
參數 描述 name 模塊的數組名,也是外部制定的數組名 type 模塊數組的數據類型 num_point 用來獲取用戶在加載模塊時傳遞的參數個數,為NULL時,表示不關心用戶傳遞的參數個數 perm 訪問權限

使用

static int  array[3];
int         num;
module_param_array(array, int, &num, 0644);
MODULE_PARM_DESC(array, "Get an array from user...\n");

param驅動源碼


驅動源碼param.c


#include 
#include 
#include 


/*
 *  在模塊裡面, 聲明一個變量(全局變量),
 *  用來接收用戶加載模塊哦時傳遞的參數
 *
 *  module_param(name, type, perm)
 **/
static int value = 0;
module_param(value, int, 0644);
MODULE_PARM_DESC(value_int, "Get an value from user...\n");

/*
 *  在模塊內部變量的名字和加載模塊時傳遞的參數名字不同
 *
 *  module_param_named(name_out, name_in, type, perm)
 *
 *  @name_out    加載模塊時,參數的名字
 *  @name_in     模塊內部變量的名字
 *  @type        參數類型
 *  @perm        訪問權限
 * */
static int  value_in = 0;
module_param_named(value_out, value_in, int, 0644);
MODULE_PARM_DESC(value_in, "value_in named var_out...\n");


/*
 *  加載模塊的時候, 傳遞字符串到模塊的一個全局字符數組裡面
 *
 *  module_param_string(name, string, len, perm)
 *
 *  @name   在加載模塊時,參數的名字
 *  @string 模塊內部的字符數組的名字
 *  @len    模塊內部的字符數組的大小
 *  #perm   訪問權限
 *
 * */
static char *string = NULL;
module_param(string, charp, 0644);
MODULE_PARM_DESC(string, "Get an string(char *) value from user...\n");


static char buffer[20] = "gatieme";
module_param_string(buffer, buffer, sizeof(buffer), 0644);
MODULE_PARM_DESC(value_charp, "Get an string buffer from user...\n");


/*
 *  加載模塊的時候, 傳遞參數到模塊的數組中
 *
 *  module_param_array(name, type, num_point, perm)
 *
 *  @name       模塊的數組名,也是外部制定的數組名
 *  @type       模塊數組的數據類型
 *  @num_point  用來獲取用戶在加載模塊時傳遞的參數個數,
 *              為NULL時,表示不關心用戶傳遞的參數個數
 *  @perm       訪問權限
 *
 * */
static int  array[3];
int         num;
module_param_array(array, int, &num, 0644);
MODULE_PARM_DESC(array, "Get an array from user...\n");




int __init  param_module_init(void)
{
    int index = 0;

    printk("\n---------------------\n");
    printk("value       : %d\n", value);
    printk("value_in    : %d\n", value_in);
    printk("string      : %s\n", string);
    printk("buffer      : %s\n", buffer);

    for(index = 0; index < num; index++)
    {
    printk("array[%2d]   :   %d\n", index, array[index]);
    }
    printk("---------------------\n");

    return 0;
}

void __exit param_module_exit(void)
{
    printk("\n---------------------\n");
    printk("exit param dobule\n");
    printk("---------------------\n");
}


module_init(param_module_init);
module_exit(param_module_exit);


Makefile




obj-m := param.o

KERNELDIR ?= /lib/modules/$(shell uname -r)/build

PWD := $(shell pwd)

all:
    make -C $(KERNELDIR) M=$(PWD) modules

clean:
    make -C $(KERNELDIR) M=$(PWD) clean

參數傳遞過程


sudo insmod param.ko value=100 value_out=200 string="gatieme" buffer="Hello-World" array=100,200,300

這裡寫圖片描述

dmesg查看

這裡寫圖片描述

sudo rmmod param

這裡寫圖片描述

使用modinfo查看參數

modinfo -p param.ko

這裡寫圖片描述

動態修改模塊參數


首先查看一下sysfs目錄下的本模塊參數信息

ls /sys/module/param/parameters

這裡寫圖片描述

動態修改
這裡寫圖片描述

Copyright © Linux教程網 All Rights Reserved