教你如何註冊proc文件系統

分類: LINUX

有些時候編寫的內核模塊,爲了具有更高的可調試性,通常會使用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),謝謝。

發佈了1 篇原創文章 · 獲贊 2 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章