sysctl使用方法的变化

内核版本:3.6

Author:zhangskd @ csdn blog


Change


在v3.4中包含一个patch,提交者Eric W. Biederman描述如下:

Rewrite of sysctl for speed and charity.

Insert/remove/Lookup in sysctl are now O(NlogN) operations, and are no longer bottlenecks in the

process of adding and removing network devices.

sysctl is now focused on being a filesystem instead of system call and the code can be found in

fs/proc/proc_sysctl.c. Hopefully this means the code is now approachable.

可见sysctl的实现发生了较大的变化。


但是这对sysctl的使用有什么影响呢?再来看另一个相关patch:

sysctl: Add register_sysctl for normal sysctl users

The plan is to convert all callers of register_sysctl_table and register_sysctl_paths to register_sysctl.

The interface to register_sysctl is enough nicer. This should make the callers a bit more readable.

Additionally after the conversion the 230 lines of backwards compatibility can be removed.


可见sysctl的注册函数发生了变化,现在是:

  1. /**
  2. * register_sysctl - register a sysctl table
  3. * @path: The path to the directory the sysctl table is in.
  4. * @table: the table structure
  5. *
  6. * Register a sysctl table. @table should be a filled in ctl_table array.
  7. * A completely 0 filled entry terminates the table.
  8. *
  9. * See __register_sysctl_table for more details.
  10. */
  11. struct ctl_table_header *register_sysctl (const char *path, struct ctl_table *table);
/**
 * register_sysctl - register a sysctl table
 * @path: The path to the directory the sysctl table is in.
 * @table: the table structure
 *
 * Register a sysctl table. @table should be a filled in ctl_table array.
 * A completely 0 filled entry terminates the table.
 *
 * See __register_sysctl_table for more details.
 */

struct ctl_table_header *register_sysctl (const char *path, struct ctl_table *table);

之前的注册函数为:

  1. struct ctl_table_header *register_sysctl_table (struct ctl_table *table);
struct ctl_table_header *register_sysctl_table (struct ctl_table *table);

也就是说现在可以通过注册函数来指定注册的路径,更加方便了。

注销函数不变:

  1. /**
  2. * unregister_sysctl_table - unregister a sysctl table hierarchy
  3. * @header: the header returned from register_sysctl_table
  4. *
  5. * Unregisters the sysctl table and all children. proc entires may not actually
  6. * be removed until they are no longer used by anyone.
  7. */
  8. void unregister_sysctl_table (struct ctl_table_header *header);
/**
 * unregister_sysctl_table - unregister a sysctl table hierarchy
 * @header: the header returned from register_sysctl_table
 *
 * Unregisters the sysctl table and all children. proc entires may not actually
 * be removed until they are no longer used by anyone.
 */
void unregister_sysctl_table (struct ctl_table_header *header);

structure

现在的ctl_table:

@include/linux/sysctl.h

  1. /* A sysctl table is an array of struct ctl_table: */
  2. struct ctl_table
  3. {
  4. const char *procname; /* Text ID for /proc/sys, or zero,文件名 */
  5. void * data;
  6. int maxlen;
  7. umode_t mode;
  8. struct ctl_table *child; /* Deprecated */
  9. proc_handler *proc_handler; /* Callback for text formatting,读写操作函数 */
  10. struct ctl_table_poll *poll;
  11. void *extra1; /* 变量的最小值min */
  12. void *extra2; /* 变量的最大值max */
  13. }
/* A sysctl table is an array of struct ctl_table: */
struct ctl_table
{
    const char *procname; /* Text ID for /proc/sys, or zero,文件名 */
    void * data;
    int maxlen;
    umode_t mode;
    struct ctl_table *child; /* Deprecated */
    proc_handler *proc_handler; /* Callback for text formatting,读写操作函数 */
    struct ctl_table_poll *poll;
    void *extra1; /*  变量的最小值min */
    void *extra2; /* 变量的最大值max */
}

proc_handler的常用取值:

proc_dointvec /* 读写一个包含一个或多个整数的数组*/

proc_dostring /* 读写一个字符串*/

proc_dointvec_minmax /* 写的数组必须在min~max范围内*/

一个instance:

@net/ipv4/sysctl_net_ipv4.c

  1. static struct ctl_table ipv4_table[] = {
  2. ...
  3. {
  4. .procname = "tcp_congestion_control",
  5. .mode = 0644;
  6. .maxlen = TCP_CA_NAME_MAX,
  7. .proc_handler = proc_tcp_congestion_control,
  8. },
  9. ...
  10. {
  11. .procname = "tcp_early_retrans",
  12. .data = &sysctl_tcp_early_retrans,
  13. .maxlen = sizeof(int),
  14. .mode = 0644,
  15. .proc_handler = proc_dointvec_minmax,
  16. .extra1 = &zero,
  17. .extra2 = &two,
  18. },
  19. ...
  20. };
static struct ctl_table ipv4_table[] = {
    ...
    {
        .procname = "tcp_congestion_control",
        .mode = 0644;
        .maxlen = TCP_CA_NAME_MAX,
        .proc_handler = proc_tcp_congestion_control,
    },
    ...
    {
        .procname = "tcp_early_retrans",
        .data = &sysctl_tcp_early_retrans,
        .maxlen = sizeof(int),
        .mode = 0644,
        .proc_handler = proc_dointvec_minmax,
        .extra1 = &zero,
        .extra2 = &two,
    },
    ...
};

这些选项的简要说明在:Documentation/networking/ipv4/*

这些选项的定义在:net/ipv4/tcp_input.c

command

sysctl — configure kernel parameters at runtime

sysctl is used to modify kernel parameters at runtime. The parameters available are those listed under /proc/sys/.

Procfs is required for sysctl support in Linux. You can use sysctl to both read and write sysctl data.

使用:

sysctl net.ipv4.tcp_congestion_control // read

sysctl -w net.ipv4.tcp_congestion_control = "cubic" // write

example

这是新的使用方法示例:

  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/sysctl.h>
  4. #include <linux/kernel.h>
  5. static char path[] = "net/test";
  6. static int zero = 0;
  7. static int two = 2;
  8. int sysctl_tcp_new;
  9. static struct ctl_table_header *header;
  10. static struct ctl_table new[] = {
  11. {
  12. .procname = "tcp_new",
  13. .data = &sysctl_tcp_new,
  14. .maxlen = sizeof(int),
  15. .mode = 0644,
  16. .proc_handler = proc_dointvec_minmax,
  17. .extra1 = &zero,
  18. .extra2 = &two
  19. },
  20. { }
  21. };
  22. static int __init sysctl_module_init(void)
  23. {
  24. header = register_sysctl(path, new);
  25. if(!header) {
  26. printk(KERN_ERR"register_sysctl() failed.\n");
  27. return -1;
  28. }
  29. return 0;
  30. }
  31. static void __exit sysctl_module_exit(void)
  32. {
  33. if(header)
  34. unregister_sysctl_table(header);
  35. }
  36. module_init(sysctl_module_init);
  37. module_exit(sysctl_module_exit);
  38. MODULE_AUTHOR("zhangsk");
  39. MODULE_LICENSE("GPL");
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sysctl.h>
#include <linux/kernel.h>

static char path[] = "net/test";
static int zero = 0;
static int two = 2;
int sysctl_tcp_new;

static struct ctl_table_header *header;

static struct ctl_table new[] = {
	{
		.procname = "tcp_new",
		.data = &sysctl_tcp_new,
		.maxlen = sizeof(int),
		.mode = 0644,
		.proc_handler = proc_dointvec_minmax,
		.extra1 = &zero,
		.extra2 = &two
	},
	{ }
};

static int __init sysctl_module_init(void)
{
	header = register_sysctl(path, new);
	if(!header) {
		printk(KERN_ERR"register_sysctl() failed.\n");
		return -1;
	}
	return 0;
}

static void __exit sysctl_module_exit(void)
{
	if(header)
		unregister_sysctl_table(header);
}

module_init(sysctl_module_init);
module_exit(sysctl_module_exit);
MODULE_AUTHOR("zhangsk");
MODULE_LICENSE("GPL");

模块加载时,就自动创建目录/proc/sys/net/test/,并在其下创建文件tcp_new,取值可为0、1或2。

模块卸载时,此目录则会被删除,当然这是在没人使用了之后。

这是旧的使用方法示例:

  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/sysctl.h>
  4. static int zero = 0;
  5. static int two = 2;
  6. int sysctl_tcp_new;
  7. static struct ctl_table_header *header;
  8. static struct ctl_table my_table[] = {
  9. {
  10. .procname = "tcp_new",
  11. .data = &sysctl_tcp_new,
  12. .maxlen = sizeof(int),
  13. .mode = 0644,
  14. .proc_handler = proc_dointvec_minmax,
  15. .extra1 = &zero,
  16. .extra2 = &two, },
  17. {},
  18. };
  19. static struct ctl_table test_dir_table[] = {
  20. {
  21. .procname = "test",
  22. .mode = 0555,
  23. .child = my_table,
  24. },
  25. {},
  26. };
  27. static struct ctl_table net_dir_table[] = {
  28. {
  29. .procname = "net",
  30. .mode = 0555,
  31. .child = test_dir_table,
  32. },
  33. {},
  34. };
  35. static int __init sysctl_module_init(void)
  36. {
  37. header = register_sysctl_table(net_dir_table);
  38. if(!header) {
  39. printk(KERN_ERR"register_sysctl_table() failed.\n");
  40. return -1;
  41. }
  42. return 0;
  43. }
  44. static void __exit sysctl_module_exit(void)
  45. {
  46. if(header)
  47. unregister_sysctl_table(header);
  48. }
  49. module_init(sysctl_module_init);
  50. module_exit(sysctl_module_exit);
  51. MODULE_AUTHOR("zhangsk");
  52. MODULE_LICENSE("GPL");

转载地址:http://blog.csdn.net/zhangskd/article/details/8447277
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sysctl.h>

static int zero = 0;
static int two = 2;
int sysctl_tcp_new;

static struct ctl_table_header *header;

static struct ctl_table my_table[] = {
        {
                .procname = "tcp_new",
                .data = &sysctl_tcp_new,
                .maxlen = sizeof(int),
                .mode = 0644,
                .proc_handler = proc_dointvec_minmax,
                .extra1 = &zero,
                .extra2 = &two, },
        {},
};

static struct ctl_table test_dir_table[] = {
        {
                .procname = "test",
                .mode = 0555,
                .child = my_table,
        },
        {},
};

static struct ctl_table net_dir_table[] = {
        {
                .procname = "net",
                .mode = 0555,
                .child = test_dir_table,
        },
        {},
};

static int __init sysctl_module_init(void)
{
        header = register_sysctl_table(net_dir_table);
        if(!header) {
                printk(KERN_ERR"register_sysctl_table() failed.\n");
                return -1;
        }
        return 0;
}

static void __exit sysctl_module_exit(void)
{
        if(header)
                unregister_sysctl_table(header);
}

module_init(sysctl_module_init);
module_exit(sysctl_module_exit);
MODULE_AUTHOR("zhangsk");
MODULE_LICENSE("GPL");


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值