用户空间与内核空间通讯接口之sysctl
2015-06-28 13:11
295 查看
概述
Sysctl是一种用户应用来设置和获得运行时内核的配置参数的一种有效方式,通过这种方式,用户应用可以在内核运行的任何时刻来改变内核的配置参数,也可以在任何时候获得内核的配置参数。通常,内核的这些配置参数也出现在proc文件系统的/proc/sys
目录下,用户应用可以直接通过这个目录下的文件来实现内核配置的读写操作。使用register_sysctl_table方式实现内核数据交互。
数据结构
/* A sysctl table is an array of struct ctl_table: */ struct ctl_table { int ctl_name; /* Binary ID */ const char *procname; /* Text ID for /proc/sys, or zero */ void *data; int maxlen; mode_t mode; struct ctl_table *child; struct ctl_table *parent; /* Automatically set */ proc_handler *proc_handler; /* Callback for text formatting */ ctl_handler *strategy; /* Callback function for all r/w */ void *extra1; void *extra2; };
成员变量解释:
const char * procname; / * 表示在 proc/sys/下显示的文件名称 * /
void * data; / * 表示对应于内核中的变量名称 * /
int maxlen; / * 表示条目允许的最大长度 * /
mode_t mode; / * 条目在proc文件系统下的访问权限 * /
struct ctl_table *child;
struct ctl_table * parent; / * Automatically set * /
proc_handler * proc_handler; / * 回调函数&proc_dointvec/ &proc_dostring * /
字段maxlen,它主要用于字符串内核变量,以便在对该条目设置时,对超过该最大长度的字符串截掉后面超长的部分。
字段proc_handler,表示回调函数
对于整型内核变量,应当设置为&proc_dointvec
而对于字符串内核变量,则设置为 &proc_dostring。
Sysctl 条目也可以是目录,此时 mode 字段应当设置为 0555,否则通过 sysctl 系统调用将无法访问它下面的 sysctl 条目,child 则指向该目录条目下面的所有条目,对于在同一目录下的多个条目,不必一一注册,用户可以把它们组织成一个 struct ctl_table 类型的数组,然后一次注册就可以。
注册register_sysctl_table
注册sysctl条目使用函数register_sysctl_table,函数原型如下:struct ctl_table_header *register_sysctl_table(struct ctl_table *table)
第一个参数为定义的struct ctl_table结构的sysctl条目或条目数组指针;
卸载unregister_sysctl_table
当模块卸载时,需要使用函数unregister_sysctl_table,其原型:void unregister_sysctl_table(struct ctl_table_header * header)
其中struct ctl_table_header是通过函数register_sysctl_table
注册时返回的结构体指针。
事例代码
#include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/sysctl.h> static int sysctl_kernusr_data = 1024; static int kernusr_callback(ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int rc; int *data = table->data; printk(KERN_INFO "original value = %d\n", *data); rc = proc_dointvec(table, write, buffer, lenp, ppos); if (write) printk(KERN_INFO "this is write operation, current value = %d\n", * data); return rc; } static struct ctl_table kernusr_ctl_table[] = { { .procname = "kernusr", .data = &sysctl_kernusr_data, .maxlen = sizeof(int), .mode = 0644, .proc_handler = kernusr_callback, }, { /* sentinel */ }, }; static struct ctl_table_header *sysctl_header; static int __init sysctl_example_init(void) { sysctl_header = register_sysctl_table(kernusr_ctl_table); if (sysctl_header == NULL) { printk(KERN_INFO "ERR: register_sysctl_table!"); return -1; } printk(KERN_INFO "sysctl register success.\n"); return 0; } static void __exit sysctl_example_exit(void) { unregister_sysctl_table(sysctl_header); printk(KERN_INFO "sysctl unregister success.\n"); } module_init(sysctl_example_init); module_exit(sysctl_example_exit); MODULE_LICENSE("GPL");
编译成ko然后装载到内核
insmod ktest.ko
成功注册到/proc文件系统。
改变kernusr的值,然后查看修改是否成功
可以看到修改的值通过proc 文件下发到内核。
卸载模块
可以看到模块被成功卸载了
相关文章推荐
- 露巧不如藏拙
- C语言打印心图案----真好玩
- centos 下安装ati显卡驱动方法
- C语言学习资料下载
- 系统吞吐量、TPS(QPS)、用户并发量、性能测试概念和公式
- 深入理解Linux中内存管理
- 怎样学编程
- Ubuntu server 14.04 LTS 多网卡绑定实现负载均衡
- Android 数据抓取——在线音乐播放器的实现
- hdu 1242 Rescue
- js——cookie
- 让QT对话框显示中文
- Cross Compiling Python for Embedded Linux
- ubuntu安装apache
- select选择框js小插件
- shell学习小总结----本章小结
- 空间插值文献阅读(Geostatistical approaches for incorporating elevation into the spatial interpolation of rainfall)
- dubbo的基本使用
- Mysql优化一 储存引擎的选择
- 我发现成功的人都有共同的特点