用户-内核交互-sysctl

    技术2022-05-18  26

    在内核模块中,每一个 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); }


    最新回复(0)