使用sysctl来实现内核参数修改

//header: sysctl-exam.h


#ifndef _SYSCTL_EXAM_H


#define _SYSCTL_EXAM_H


#include

 

#define MY_ROOT (CTL_CPU + 10)


#define MY_MAX_SIZE 256

 

enum {


        MY_INT_EXAM = 1,


        MY_STRING_EXAM = 2,


}; //sysctl 条目 ID,用户态应用和内核模块需要这些 ID 来操作和注册 sysctl 条目


#endif

 

 

//kernel module: sysctl-exam-kern.c


#include


#include


#include


#include "sysctl-exam.h"

 

static char mystring[256];


static int myint;  // 定义模块内部变量

 

static struct ctl_table my_sysctl_exam[] = {   // 在该内核模块中,每一个 sysctl 条目对应一个 struct ctl_table 结构


        {


                .ctl_name       = MY_INT_EXAM,


                .procname       = "myint",


                .data           = &myint,


                .maxlen         = sizeof(int),


                .mode           = 0666,  //条目在proc文件系统下的访问权限


                .proc_handler   = &proc_dointvec, //在通过proc设置时的处理函数(字段proc_handler,对于整型内核变量,应当设置为&proc_dointvec,而对于字符串内核变量,则设置为 &proc_dostring),


        },


        {


                .ctl_name       = MY_STRING_EXAM,


                .procname       = "mystring",


                .data           = mystring,


                .maxlen         = MY_MAX_SIZE,


                .mode           = 0666,


                .proc_handler   = &proc_dostring,


                .strategy       = &sysctl_string, //字符串处理策略(字段strategy,一般这是为&sysctl_string)。


        },


        {


                .ctl_name = 0  //必须把数组的最后一个结构设置为NULL


        }


};

 

static struct ctl_table my_root = {


        .ctl_name       = MY_ROOT,


        .procname       = "mysysctl",


        .mode           = 0555,


        .child          = my_sysctl_exam,


};//Sysctl 条目可以是目录,此时 mode 字段应当设置为 0555,否则通过 sysctl 系统调用将无法访问它下面的 sysctl 条目,

//child 则指向该目录条目下面的所有条目,对于在同一目录下的多个条目,不必一一注册,用户可以把它们组织成一个 struct ctl_table 类型的数组,然后一次注册就可以

 

 

static struct ctl_table_header * my_ctl_header;

 

static int __init sysctl_exam_init(void)


{
        my_ctl_header = register_sysctl_table(&my_root, 0);  //第一个参数为定义的struct ctl_table结构的sysctl条目或条目数组指针

                                                                                             //第二个参数为插入到sysctl条目表中的位置,如果插入到末尾,应当为0,如果插入到开头,则为非0

 

        return 0;


}

 

static void __exit sysctl_exam_exit(void)


{
        unregister_sysctl_table(my_ctl_header);


}

 

module_init(sysctl_exam_init);


module_exit(sysctl_exam_exit);


MODULE_LICENSE("GPL");

 

用户态应用通过sysctl系统调用来查看和设置前面内核模块注册的sysctl条目

用户空间代码如下

int myintctl[] = {MY_ROOT, MY_INT_EXAM};


int mystringctl[] = {MY_ROOT, MY_STRING_EXAM};

 

int sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,void *newval, size_t newlen)


{


        struct __sysctl_args args={name,nlen,oldval,oldlenp,newval,newlen};


        return _sysctl(&args);


}

 

                if (sysctl(myintctl, SIZE(myintctl), &oldmyint, &oldmyintlen, &newmyint, newmyintlen)) {


                        perror("sysctl");


                        exit(-1);


                }


                else {


                        printf("old value: mysysctl.myint = %d\n", oldmyint);


                        printf("new value: mysysctl.myint = %d\n", newmyint);


                }

 


                if (sysctl(mystringctl, SIZE(mystringctl), oldmystring, &oldmystringlen, newmystring, newmystringlen)) {


                        perror("sysctl");


                        exit(-1);


                }
                else {


                        printf("old vale: mysysctl.mystring = \"%s\"\n", oldmystring);


                        printf("new value: mysysctl.mystring = \"%s\"\n", newmystring);


                }

 

 

 

 

 

你可能感兴趣的:(linuxOS)