리눅스

register sysctl table

macro 2010. 9. 30. 10:17
반응형

- 커널 파라미터를 읽거나 쓸때 sysctl 을 사용한다.
- sysctl은 /proc/sys 디렉토리 트리 에서 해당 값을 찾는다.

- 따라서 커널 2.6.23 기준에서 /proc/sys 에 파일을 생성하는 방법에 대해 알아본다. (2.4와 차이가 있다)

1. 2.4와 비교하여 2.6에서는 struct ctl_table 구조체 멤버가 몇개 변경되었다.
2. register_sysctl_table 함수의 파라미터가 2개에서 1개로 변경되었다.
3. 위 함수의 파라미터로 넘어가는 struct ctl_table 를 셋팅할 때, 내가 만약 /proc/sys/net/macro 라는 파일을 만들고 싶다면,
4. struct ctl_table 의 내가 만들고자 하는 macro 셋팅은 다음과 같다.
{
.ctl_name = CTL_UNNUMBERED,
            .procname = "macro",
            .data = &sysctl_macro,
            .maxlen = sizeof(int),
            .mode = 0644,
            .child = NULL,
            .proc_handler = &proc_dointvec},
5. 위에서 ctl_name 의 값이 2.4와는 다르게 CTL_UNNUMBERED 로 셋팅해야 한다. 이 값으로 셋팅하지 않고 유저 디파인된 값으로 셋팅하게 되면, 모듈 컴파일은 되나, insmod 시 sysctl table check failed: ... Unknown sysctl binary path 라는 에러가 발생하며, 모듈 인서트가 되지 않는다.

< example : /proc/sys/net/ipv4/macro 디렉토리에 macro_file1, macro_file2 라는 파일 만듬. >

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/sysctl.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ctype.h>
#include <net/ip.h>

#define MODULE_VERS "1.0"
#define MODULE_NAME "sysctl_example"


int macro_one = 5;
int macro_two = 1;


/* sysctl table */
struct macro_sysctl_table {
        struct ctl_table_header *sysctl_header;
        ctl_table macro_vars[3];
        ctl_table macro_dir[2];
        ctl_table ipv4_dir[2];
        ctl_table root_dir[2];
};

static struct macro_sysctl_table ipv4_macro_table = {
        NULL,
        {{.ctl_name = CTL_UNNUMBERED,
                .procname = "macro_file1",
                .data = &macro_one,
                .maxlen = sizeof(int),
                .mode = 0644,
                .child = NULL,
                .proc_handler =  &proc_dointvec},
         {.ctl_name = CTL_UNNUMBERED,
                .procname = "macro_file2",
                .data = &macro_two,
                .maxlen = sizeof(int),
                .mode = 0644,
                .child = NULL,
                .proc_handler = &proc_dointvec},
         {0}},
        {{.ctl_name = CTL_UNNUMBERED,
                .procname = "macro",
                .mode = 0555,
                .child =  ipv4_macro_table.macro_vars},
         {0}},
        {{.ctl_name = NET_IPV4,
                .procname = "ipv4",
                .mode = 0555,
                .child = ipv4_macro_table.macro_dir},
         {0}},
        {{.ctl_name = CTL_NET,
                .procname = "net",
                .mode = 0555,
                .child = ipv4_macro_table.ipv4_dir},
         {0}}
};

static int __init init_example(void)
{
        printk("sssssssssssssssss\n");
        ipv4_macro_table.sysctl_header =
                register_sysctl_table(ipv4_macro_table.root_dir);
        if(!ipv4_macro_table.sysctl_header){
                printk("my god!! \n");
                return -ENOMEM;
        }

        printk("ok sysctl\n");
        return 0;
}


static void __exit cleanup_example(void)
{
        unregister_sysctl_table(ipv4_macro_table.sysctl_header);
        printk("remove\n");
}


module_init(init_example);
module_exit(cleanup_example);

MODULE_AUTHOR("omw");
MODULE_DESCRIPTION("sysctl examples");
MODULE_LICENSE("GPL");
                                     


반응형