用户-内核交互-sysctl

来源:互联网 发布:淘宝优惠卷名称怎么写 编辑:程序博客网 时间:2024/05/23 01:12

在内核模块中,每一个 sysctl 条目对应一个 struct ctl_table 结构

/* A sysctl table is an array of struct ctl_table: */
struct ctl_table
{
      int ctl_name;                /* 要注册的 sysctl 条目的 ID, 同一层的结点用不同的数字来标识*/
      const char *procname;        /* Text ID for /proc/sys, or zero 在 proc 下的名称*/
      void *data;                  /* 对应的内核变量,该字段的赋值必须是指针*/
      int maxlen;                  /* 条目允许的最大长度,主要用于字符串内核变量,以便在对该条目设置时,对超过该最大长度的字符串截掉后面超长的部分*/
      mode_t mode;                 /* 条目在proc文件系统下的访问权限,0666,sysctl条目可以是目录,应当设置为 0555*/
      ctl_table *child;            /* sysctl条目是目录时,指向该目录条目下的所有条目,对于在同一目录下的多个条目,不必一一注册,用户可以把它们组织成一个 struct ctl_table 类型的数组,然后一次注册,但此时必须把数组的最后一个结构设置为NULL,即.ctl_name = 0*/
      ctl_table *parent;           /* Automatically set */
      proc_handler *proc_handler;  /* 在通过proc设置时的处理函数,整型内核变量设为&proc_dointvec,字符串内核变量设为 &proc_dostring*/
      ctl_handler *strategy;       /* 字符串处理策略,一般这是为&sysctl_string*/
      void *extra1;
      void *extra2;
};

 

Eg:  /proc/mysysctl/myint & /proc/mysysctl/mystring

static struct ctl_table my_sysctl_exam[] = {        {                .ctl_name       = MY_INT_EXAM,                .procname       = "myint",                .data           = &myint,                .maxlen         = sizeof(int),                .mode           = 0666,                .proc_handler   = &proc_dointvec,        },        {                .ctl_name       = MY_STRING_EXAM,                .procname       = "mystring",                .data           = mystring,                .maxlen         = MY_MAX_SIZE,                .mode           = 0666,                .proc_handler   = &proc_dostring,                .strategy       = &sysctl_string,        },        {                .ctl_name = 0        }}; static struct ctl_table my_root = {        .ctl_name       = MY_ROOT,        .procname       = "mysysctl",        .mode           = 0555,        .child          = my_sysctl_exam,}; 

++++++++++++++++++++++++++++++++++++++++

 

注册sysctl条目

struct ctl_table_header *(struct ctl_table *, int);


第一个参数为定义的struct ctl_table结构的sysctl条目或条目数组指针,
第二个参数为插入到sysctl条目表中的位置,如果插入到末尾,应当为0,如果插入到开头,则为非0。
内核把所有的sysctl条目都组织成sysctl表。
调用成功时返回结构struct ctl_table_header,它就是sysctl表的表头,解注册函数使用它来卸载相应的sysctl条目。

解注册sysctl条目

当模块卸载时,解注册通过函数register_sysctl_table注册的sysctl条目
void unregister_sysctl_table(struct ctl_table_header *);

 

++++++++++++++++++++++++++++++++++++++++

 

用户态下,可以直接使用cat,echo等查看和修改/proc/sys下对应文件中的系统参数,进而影响内核模块的行为。


在用户态应用程序中可以调用sysctl函数读写系统参数

#include
#include
#include
_syscall1(int, _sysctl, struct __sysctl_args *, args);

用于读写系统参数(man 2 sysctl)

int _sysctl(struct __sysctl_args *args);
这个是系统调用函数,sysctl函数是对它的封装。返回0:成功;-1:失败
参数struct __sysctl_args {
    int *name;         /* 整形数组,每个数组元素代表系统参数存取路径上的一个文件或目录名,例如/proc/sys/kernel用CTL_KERN表示*/
    int nlen;          /* 上面整形数组大小*/
    void *oldval;      /* 当读取系统参数时,用于存取系统参数值,也就是/proc/sys/下的某个文件内容*/
    size_t *oldlenp;   /* 上面所记录长度*/
    void *newval;      /* 当写系统参数时,记录所要写入的新值*/
    size_t newlen;     /* 上面所记录长度*/
};

 

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);
}

原创粉丝点击