(1)引入原因

       在用户态下编程可以通过main()来传递命令行参数(具体可见C语言高级中的一篇文章),而编写一个内核模块则可通过module_param()来传递命令行参数。
(2)实现

        module_param宏是Linux 2.6内核中新增的,该宏被定义在include/linux/moduleparam.h文件中,具体定义如下:

/* Helper functions: type is byte, short, ushort, int, uint, long,  ulong, charp, bool or invbool, or XXX if you define param_get_XXX,param_set_XXX and param_check_XXX. */
   #define module_param_named(name, value, type, perm)              
    param_check_##type(name, &(value));                  
    module_param_call(name, param_set_##type, param_get_##type, &value, perm);
    __MODULE_PARM_TYPE(name, #type)

    #define module_param(name, type, perm)              module_param_named(name, name, type, perm)

(3)module_param使用了3个参数:变量名,它的类型,以及一个权限掩码用来做一个辅助的sysfs入口。这个宏定义应当放在函数之外,典型的是出现在源文件的前面。
eg: static char *whom="world"
       static int    tige=1;
       module_param(tiger,int,S_IRUGO);
       module_param(whom,charp,S_IRUGO);
(4)数组参数

       用逗号间隔的列表提供值,模块加载也支持。声明一个数组参数,使用:module_param_array(name,type,num,perm);这里 name 是你的数组的名子(也是参数名),
type 是数组元素的类型,num 是一个整型变量,perm 是通常的权限值。模块加载者拒绝比数组能放下的多的值。

(5)实例

1,编写一个moduleparam.c,如下:

#include <linux/init.h>  
#include <linux/module.h>  
#include <linux/moduleparam.h>  
  
MODULE_LICENSE("Dual BSD/GPL");  
  
static char *who = "world";  
static int times = 1;  
module_param(times,int,S_IRUSR);  
module_param(who,charp,S_IRUSR);  
  
static int __init hello_init(void)  
{  
        int i;  
        for(i = 0;i < times;i++)  
                printk(KERN_ALERT"(%d)hello,%s! /n",i,who);  
        return 0;  
  
}  
  
static void __exit hello_exit(void)  
{  
        printk(KERN_ALERT"Goodbye ,%s! /n",who);  
}  
  
module_init(hello_init);  
module_exit(hello_exit);
2,编写一个makefile文件,如下:

obj-m:=moduleparam.o  
CURRENT_PATH:=$(shell pwd)  
VERSION_NUM:=$(shell uname -r)  
LINUX_PATH:=/usr/src/linux-headers-$(VERSION_NUM)  
  
all:  
	make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules  
clean:  
	make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean 
       执行make后编译生成moduleparam.ko。然后终端执行:sudo insmod moduleparam.ko who=pig times=4(如果出现insmod: error inserting 'moduleparam.ko': -1 File exists,就要先rmmod老的ko,再push),再用dmesg就可以看到内核消息末尾有:

[ 1637.910012] (0)hello,pig! /n
[ 1637.910039] (1)hello,pig! /n
[ 1637.910044] (2)hello,pig! /n
[ 1637.910047] (3)hello,pig! /n

        可见模块在加载时调用了其后的模块参数。

===========================内核线程kthread实例======================================

#include <linux/init.h>  
#include <linux/module.h>  
#include <linux/moduleparam.h>  
#include <linux/init.h>   
#include <linux/module.h>   
#include <linux/kthread.h>  
#include <linux/delay.h> 

MODULE_LICENSE("Dual BSD/GPL");  
  
static struct task_struct *tsk;

static int thread_function(void *data)  
{  
    int time_count = 0;  
    do {  
        printk(KERN_INFO "thread_function: %d times", ++time_count);  
        msleep(1000);  
    }while(!kthread_should_stop() && time_count<=30);  
    return time_count;  
}  


static int __init hello_init(void)  
{  
		printk(KERN_INFO "Hello, world!\n");   
    tsk = kthread_run(thread_function, NULL, "mythread%d", 1);  
    if (IS_ERR(tsk)) {  
        printk(KERN_INFO "create kthread failed!\n");  
    }  
    else {  
        printk(KERN_INFO "create ktrhead ok!\n");  
    }
    return 0;  
}  
  
static void __exit hello_exit(void)  
{  
	printk(KERN_INFO "Hello, exit!\n");  
    if (!IS_ERR(tsk)){  
        int ret = kthread_stop(tsk);  
        printk(KERN_INFO "thread function has run %ds\n", ret);  
    }
}  
  
module_init(hello_init);  
module_exit(hello_exit);
      提到了两种线程退出的方式,计数到30自动退出;或者在模块卸载时推出线程。注意:kthread_should_stop和kthread_stop搭配使用,如果没有前者,后者是不起作用的。insmod的结果:



参考原文:http://www.phpfans.net/article/htmls/201011/MzIxNzY3.html

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐