sysctl

来源:互联网 发布:win10网络图标不显示 编辑:程序博客网 时间:2024/05/16 06:23
在kernel/sysctl.c 中有定义sysctl_initint __init sysctl_init(void){struct ctl_table_header *hdr;hdr = register_sysctl_table(sysctl_base_table);kmemleak_not_leak(hdr);return 0;}这个函数会在proc/sys 目录下新建四个目录,这四个新建的目录是在sysctl_base_table 中有定义static struct ctl_table sysctl_base_table[] = {{.procname= "kernel",.mode= 0555,.child= kern_table,},{.procname= "vm",.mode= 0555,.child= vm_table,},{.procname= "fs",.mode= 0555,.child= fs_table,},{.procname= "debug",.mode= 0555,.child= debug_table,},{.procname= "dev",.mode= 0555,.child= dev_table,},{ }};这四个目录下可以新建子目录或者新建文件,以kernel 这个目录为例static struct ctl_table kern_table[] = {{.procname= "sched_child_runs_first",.data= &sysctl_sched_child_runs_first,.maxlen= sizeof(unsigned int),.mode= 0644,.proc_handler= proc_dointvec,},}通过cat 就可以读取或者echo就可以改变sched_child_runs_first 这个参数的值。从proc_dointvec 可以知道这个值是int类型的extern unsigned int sysctl_sched_child_runs_first;

如果想在自己的驱动中往proc/sys下面添加目录或者文件的话,可以参考下面在net目录下添加net/ipv4/routestatic __net_init int sysctl_route_net_init(struct net *net){struct ctl_table *tbl;tbl = ipv4_route_flush_table;if (!net_eq(net, &init_net)) {tbl = kmemdup(tbl, sizeof(ipv4_route_flush_table), GFP_KERNEL);if (!tbl)goto err_dup;/* Don't export sysctls to unprivileged users */if (net->user_ns != &init_user_ns)tbl[0].procname = NULL;}tbl[0].extra1 = net;net->ipv4.route_hdr = register_net_sysctl(net, "net/ipv4/route", tbl);if (!net->ipv4.route_hdr)goto err_reg;return 0;err_reg:if (tbl != ipv4_route_flush_table)kfree(tbl);err_dup:return -ENOMEM;}那我们看看register_net_sysctl 是如何添加的呢?struct ctl_table_header *register_net_sysctl(struct net *net,const char *path, struct ctl_table *table){//可以看到代表net device的struct net *net 有一个变量代表/proc/sys/net 这个sysctl的路径。第二个参数path 表示要插入的路径,第三个参数表示ctl_table *tablereturn __register_sysctl_table(&net->sysctls, path, table);}struct ctl_table_header *__register_sysctl_table(struct ctl_table_set *set,const char *path, struct ctl_table *table){struct ctl_table_root *root = set->dir.header.root;struct ctl_table_header *header;const char *name, *nextname;struct ctl_dir *dir;struct ctl_table *entry;struct ctl_node *node;int nr_entries = 0;for (entry = table; entry->procname; entry++)nr_entries++;header = kzalloc(sizeof(struct ctl_table_header) + sizeof(struct ctl_node)*nr_entries, GFP_KERNEL);if (!header)return NULL;node = (struct ctl_node *)(header + 1);init_header(header, root, set, node, table);if (sysctl_check_table(path, table))goto fail;spin_lock(&sysctl_lock);dir = &set->dir;/* Reference moved down the diretory tree get_subdir */dir->header.nreg++;spin_unlock(&sysctl_lock);/* Find the directory for the ctl_table */for (name = path; name; name = nextname) {int namelen;nextname = strchr(name, '/');if (nextname) {namelen = nextname - name;nextname++;} else {namelen = strlen(name);}if (namelen == 0)continue;//找到需要插入的目录dir = get_subdir(dir, name, namelen);if (IS_ERR(dir))goto fail;}spin_lock(&sysctl_lock);//出入当前需要注册的ctl_table *tableif (insert_header(dir, header))goto fail_put_dir_locked;drop_sysctl_table(&dir->header);spin_unlock(&sysctl_lock);return header;fail_put_dir_locked:drop_sysctl_table(&dir->header);spin_unlock(&sysctl_lock);fail:kfree(header);dump_stack();return NULL;}