一、介绍
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
#include
#include
#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
#include
#include
#include
#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