一、介绍

      Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构、改变内核设置的机制。

      proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。

      它以文件系统的方式为访问系统内核数据的操作提供接口。

二、代码

      代码,是在/proc/sys/net/ipv4/下创建目录test_server/,创建文件debug_flag;读写/proc/sys/net/ipv4/test_server/debug_flag,在程序中数据debug_flag值是0,还是1(非0)。

每当来一个数据包时,就会输出一个debug_flag值。

rwproc.h:

int config_init(void);
int config_exit(void);

rwproc.c:

#include <linux/uio_driver.h>
#include <linux/platform_device.h>
#include <linux/device.h>

#include "rwproc.h"

//
struct platform_device * test_uio_device;

u8 test_uio_driver_flag = 0;

static struct ctl_table_header * test_sysctl_header = NULL;


//
u32 debug_flag = 1;
static ctl_table test_sysctl_table[] =
{
    {
        .ctl_name       = 1,
        .procname       = "debug_flag",
        .data           = &debug_flag,
        .maxlen         = sizeof(debug_flag),
        .mode           = 0644,
        .proc_handler   = &proc_dointvec
    },
    { .ctl_name = 0 }
};

static ctl_table test_ipv4_table[] =
{
    {
        .ctl_name       = 5002,
        .procname       = "test_server",
        .mode           = 0555,
        .child          = test_sysctl_table
    },
    { .ctl_name = 0 }
};

static ctl_table test_net_table[] =
{
    {
        .ctl_name       = NET_IPV4,
        .procname       = "ipv4",
        .mode           = 0555,
        .child          = test_ipv4_table
    },
    { .ctl_name = 0 }
};

static ctl_table test_root_table[] =
{
    {
        .ctl_name       = CTL_NET,
        .procname       = "net",
        .mode           = 0555,
        .child          = test_net_table
    },
    { .ctl_name = 0 }
};

struct uio_info test_uio_info =
{
    .name = "test_update_uio",
    .version = "1.0",
    .irq = UIO_IRQ_NONE,
};

int test_drv_probe(struct device * dev)
{
    test_uio_info.mem[0].addr = (unsigned long)kmalloc(4096, GFP_KERNEL);
    if((void *)test_uio_info.mem[0].addr == NULL)
    {
        printk(KERN_DEBUG"test_drv_probe fail 1.");
        return 501;
    }
    test_uio_info.mem[0].memtype = UIO_MEM_LOGICAL;
    test_uio_info.mem[0].size = 4096;
    if( uio_register_device(dev, &test_uio_info) )
    {
        printk(KERN_DEBUG"test_drv_probe fail 2.");
        return 502;
    }
    return 0;
}

int test_drv_remove(struct device * dev)
{
    uio_unregister_device(&test_uio_info);
    return 0;
}

struct device_driver test_uio_driver =
{
    .name = "test_update_uio",
    .bus = &platform_bus_type,
    .probe = test_drv_probe,
    .remove = test_drv_remove,
};

int config_init(void)
{
    int ret;

    //
    test_uio_device = platform_device_register_simple("test_update_uio", -1, NULL, 0);

    //
    ret = driver_register(&test_uio_driver);
    if(ret)
    {
        printk(KERN_DEBUG"config_init fail 1.");
        return 503;
    }
    test_uio_driver_flag = 1;

    //
    test_sysctl_header = register_sysctl_table(test_root_table);
    if( test_sysctl_header == NULL )
    {
        printk(KERN_DEBUG"config_init fail 2.");
        return 504;
    }

    return 0;
}

int config_exit(void)
{
    //
    if(test_uio_driver_flag)
    {
        driver_unregister(&test_uio_driver);
    }

    //
    platform_device_unregister(test_uio_device);
    
    //
    if(test_sysctl_header)
    {
        unregister_sysctl_table(test_sysctl_header);
    }

    return 0;
}

main.c:

#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/module.h>
#include <linux/kernel.h>

#include "rwproc.h"


MODULE_LICENSE("GPL");

extern u32 debug_flag;

unsigned int hook_mark1(unsigned int hooknum, struct sk_buff *skb,
                        const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))

{
    if (0==debug_flag) 
    {
        printk(KERN_DEBUG"debug_flag is 0.");
    }
    else if (debug_flag) 
    {
        printk(KERN_DEBUG"debug_flag is 1.");
    }
    
    return NF_ACCEPT;
}


static struct nf_hook_ops nfho_marker1;
static int init_marker(void)
{
    printk(KERN_DEBUG"enter init_marker.");

    if (0 != config_init())
    {
        config_exit();
        printk(KERN_DEBUG"config_init() error.");
        return -1;
    }

    nfho_marker1.hook=hook_mark1;
    nfho_marker1.hooknum=NF_INET_PRE_ROUTING;
    nfho_marker1.pf=PF_INET;
    nfho_marker1.priority=NF_IP_PRI_LAST;
    nf_register_hook(&nfho_marker1);

    return 0;
}

static void exit_marker(void)
{
    nf_unregister_hook(&nfho_marker1);
    
    config_exit();
    
    printk(KERN_DEBUG"leave exit_marker.");
}

module_init(init_marker);
module_exit(exit_marker);


参考资料:

      Linux下/proc目录简介:http://blog.csdn.net/zdwzzu2006/article/details/7747977

Logo

更多推荐