struct ctl_table
{
int ctl_name; /* 结点标识,同一层的结点用不同的数字来标识
此处设置的意义可以看do_sysctl()->parse_table()
*/
const char *procname; /* /proc/sys/ 下使用的文件名*/
void *data; /*内核变量的地址*/
int maxlen; /*内核变量的尺寸大小*/
mode_t mode; /*文件访问权限*/
struct ctl_table *child; /*建立文件与目录的父子关系*/
struct ctl_table *parent; /* Automatically set */
proc_handler *proc_handler; /* 当对文件读取或写入的时候 调用此函数
根据值的类型 初始化为不同的函数如字符串 proc_dostring()
*/
ctl_handler *strategy; /* 用sysctl系统调用的时候 此函数被调用 sysctl_string()*/
void *extra1;
void *extra2; /*extra1 extra2可选参数 通常定义变量的最小值 或最大值*/
};
struct ctl_table_header *register_sysctl_table(struct ctl_table *table)
fun:注册sysctl(/proc/sys)下的操作项
头文件:#include <linux/sysctl.h>
void unregister_sysctl_table(struct ctl_table_header * header)
fun:注销sysctl(/proc/sys)下的操作项
头文件:#include <linux/sysctl.h>
初始化ctl_table{}->proc_handler的函数
proc_dostring()
读写一个字符串
proc_dointvec()
读写包含一个或多个整数的数组
proc_dointvec_minmax()
类似 proc_dointvec() 但是要确定输入数据是在 min/max范围内
proc_dointvec_jiffies ()
读写整形数组 此内核变量以jiffies为单位表示,返回给用户前先转为秒数
proc_doulongvec_minmax()
类似proc_dointvec_minmax()但读取的是长整形
proc_doulongvec_ms_jiffies_minmax()
读写长整形数组 此内核变量以jiffies为单位 返回给用户前先转换为毫秒数
初始化ctl_table{}-> strategy的函数
sysctl_string()
读写一个字符串
sysctl_intvec()
读写一个整形数组 而且确定其值符合min/max
sysctl_jiffies()
读写一个以jiffies表示的值,然后将其转化为秒
sysctl_ms_jiffies()
读写一个以jiffies表示的值,然后把它装化为毫秒
举个栗子
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sysctl.h>
int g_catsize=20;
int g_catcolor = 10;
char g_catname[258] = {"miaomiao"};
enum{
KERNEL_CAT_SIZE=1,//不要从0开始
KERNEL_CAT_COLOR,
KERNEL_CAT_NAME
};
enum{
KERNEL_CAT = CTL_CPU + 11,//不要从0开始 不要和系统已有的ctl_name重复 why?看do_sysctl()->parse_table()
};
int my_proc_dointvec(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int ret = 0;
//用来处理整型数据或整型数组
ret = proc_dointvec(table,write,buffer,lenp,ppos);
printk("*********************catsize=%d catcolor=%d\n",g_catsize,g_catcolor);
return ret;
}
int my_proc_dostring(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int ret;
//用来处理字符串
ret = proc_dostring(table,write,buffer,lenp,ppos);
printk("**************************catname=%s\n",g_catname);
return ret;
}
/*对应的文件项
* /proc/sys/mycat1/catsize
/proc/sys/mycat1/catcolor
/proc/sys/mycat1/catname
* */
static ctl_table cat_attr_table[]={
{
.ctl_name = KERNEL_CAT_SIZE,
.procname = "catsize",
.data = &g_catsize,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &my_proc_dointvec //处理整型
},
{
.ctl_name = KERNEL_CAT_COLOR,
.procname = "catcolor",
.data = &g_catcolor,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &my_proc_dointvec //处理整型
},
{
.ctl_name = KERNEL_CAT_NAME,
.procname = "catname",
.data = g_catname,
.maxlen = 256,
.mode = 0644,
.proc_handler = &my_proc_dostring//处理字符串
},
{} //最后一项必须为空
};
/*
对应的目录项:
/proc/sys/mycalt1/
*/
static ctl_table mycat[]={
{
.ctl_name = KERNEL_CAT,
.procname = "mycat1",
.mode = 0555, //创建目录权限
.child = cat_attr_table //设置子文件项
},
{} //最后一项必须为空
};
static struct ctl_table_header *cat_table_header;
static int __init test_init(void)
{
//注册sysctl操作项
cat_table_header = register_sysctl_table(mycat);
if(NULL == cat_table_header)
{
printk("register error\n");
return -1;
}
return 0;
}
static void __exit test_exit(void)
{
//注销syscatl操作项
unregister_sysctl_table(cat_table_header);
return;
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");