Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3928788
  • 博文数量: 93
  • 博客积分: 3189
  • 博客等级: 中校
  • 技术积分: 4229
  • 用 户 组: 普通用户
  • 注册时间: 2009-02-02 13:29
个人简介

出没于杭州和青岛的程序猿一枚,对内核略懂一二

文章分类

全部博文(93)

文章存档

2016年(2)

2015年(3)

2014年(11)

2013年(29)

2012年(16)

2011年(5)

2010年(5)

2009年(22)

分类: LINUX

2009-06-30 15:39:41

有些时候编写的内核模块,为了具有更高的可调试性,通常会使用proc文件系统。例如netfilter的layer7模块。
下面是在2.6.24下的注册proc文件系统,并实现读写功能的代码。
在/proc/net下建立目录procdir,在该目录下注册procfile文件。

#include <linux/spinlock.h>
#include <linux/version.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_layer7.h>
#include <linux/ctype.h>
#include <linux/proc_fs.h>


MODULE_LICENSE("GPL");
MODULE_AUTHOR("LTW");
MODULE_DESCRIPTION("make proc file");
static struct nf_hook_ops procfile;
static int procnum=20;

static struct proc_dir_entry* father;

unsigned int procfile_func(unsigned int hooknum,struct sk_buff *skb,const struct net_device *in,const struct net_device *out,int(*okfn)(struct sk_buff*))
{
    printk(KERN_ALERT "OK\n");
    return NF_ACCEPT;
}

static int my_atoi(const char *s)
{
    int val = 0;

    for (;; s++) {
        switch (*s) {
            case '0'...'9':
            val = 10*val+(*s-'0');
            break;
        default:
            return val;
        }
    }
}
/* write out num_packets to userland. */
static int procfile_read_proc(char* page, char ** start, off_t off, int count,int* eof, void * data)
{
    if(procnum>99)
        printk(KERN_ALERT "procnum is too big\n");
    page[0] = procnum/10 + '0';
    page[1] = procnum%10 + '0';
    page[2] = '\n';
    page[3] = '\0';

    *eof=1;

    return 3;
}

/* Read in num_packets from userland */
static int procfile_write_proc(struct file* file, const char* buffer,
                             unsigned long count, void *data)
{
    char * foo = kmalloc(count, GFP_ATOMIC);

    if(!foo){
        return count;
    }

    if(copy_from_user(foo, buffer, count)) {
        return -EFAULT;
    }


    procnum= my_atoi(foo);
    kfree (foo);

    /* This has an arbitrary limit to make the math easier. I'm lazy.
    But anyway, 99 is a LOT! If you want more, you're doing it wrong! */

    if(procnum > 99) {
        printk(KERN_ALERT "procnum can't be > 99.\n");
        procnum = 99;
    } else if(procnum < 1) {
        printk(KERN_ALERT "procnum can't be < 1.\n");
        procnum = 1;
    }

    return count;
}


static void procfile_cleanup_proc(void)
{
    remove_proc_entry("procfile",father);
    remove_proc_entry("procdir",init_net.proc_net);
}

static void procfile_init_proc(void)
{
    struct proc_dir_entry* entry;
    father=proc_mkdir("procdir",init_net.proc_net);
    entry = create_proc_entry("procfile", 0644,father);
    entry->read_proc = procfile_read_proc;
    entry->write_proc = procfile_write_proc;
}

static int __init procfile_init(void)
{
    printk(KERN_ALERT "procfile init\n");
    procfile_init_proc();
    memset(&procfile,0,sizeof(struct nf_hook_ops));
    procfile.hook=procfile_func;
    procfile.owner=THIS_MODULE;
    procfile.pf=PF_INET;
    procfile.hooknum=NF_IP_PRE_ROUTING;
    procfile.priority=NF_IP_PRI_NAT_DST-1;
    return nf_register_hook(&procfile);
}
static void __exit procfile_exit(void)
{
    procfile_cleanup_proc();
    nf_unregister_hook(&procfile);
}
module_init(procfile_init);
module_exit(procfile_exit);

 

转载时请注明出处(http://pengliang.cublog.cn),谢谢。

阅读(4001) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~