Create file under /proc -- Manage it with standard file system

来源:互联网 发布:数据查询工具 编辑:程序博客网 时间:2024/05/16 10:22

 

/*
 *  procfs3.c -  create a "file" in /proc, use the file_operation way
 *              to manage the file.
 */

#include <linux/kernel.h>       /* We're doing kernel work */
#include <linux/module.h>       /* Specifically, a module */
#include <linux/proc_fs.h>      /* Necessary because we use proc fs */
#include <asm/uaccess.h>        /* for copy_*_user */

#define PROC_ENTRY_FILENAME     "buffer2k"
#define PROCFS_MAX_SIZE         2048

/**
 * The buffer (2k) for this module
 *
 */
static char procfs_buffer[PROCFS_MAX_SIZE];

/**
 * The size of the data hold in the buffer
 *
 */
static unsigned long procfs_buffer_size = 0;

/**
 * The structure keeping information about the /proc file
 *
 */
static struct proc_dir_entry *Our_Proc_File;

 

/**
 * This funtion is called when the /proc file is read
 *
 */
static ssize_t procfs_read(struct file *filp,   /* see include/linux/fs.h   */
                             char *buffer,      /* buffer to fill with data */
                             size_t length,     /* length of the buffer     */
                             loff_t * offset)
{
        static int finished = 0;

        /*
         * We return 0 to indicate end of file, that we have
         * no more information. Otherwise, processes will
         * continue to read from us in an endless loop.
         */
        if ( finished ) {
                printk(KERN_INFO "procfs_read: END/n");
                finished = 0;
                return 0;
        }

        finished = 1;

        /*
         * We use put_to_user to copy the string from the kernel's
         * memory segment to the memory segment of the process
         * that called us. get_from_user, BTW, is
         * used for the reverse.
         */
        if ( copy_to_user(buffer, procfs_buffer, procfs_buffer_size) ) {
                return -EFAULT;
        }

        printk(KERN_INFO "procfs_read: read %lu bytes/n", procfs_buffer_size);

        return procfs_buffer_size;      /* Return the number of bytes "read" */
}

 

/*
 * This function is called when /proc is written
 */
static ssize_t
procfs_write(struct file *file, const char *buffer, size_t len, loff_t * off)
{
        if ( len > PROCFS_MAX_SIZE )    {
                procfs_buffer_size = PROCFS_MAX_SIZE;
        }
        else    {
                procfs_buffer_size = len;
        }

        if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
                return -EFAULT;
        }

        printk(KERN_INFO "procfs_write: write %lu bytes/n", procfs_buffer_size);

        return procfs_buffer_size;
}

/*
 * This function decides whether to allow an operation
 * (return zero) or not allow it (return a non-zero
 * which indicates why it is not allowed).
 *
 * The operation can be one of the following values:
 * 0 - Execute (run the "file" - meaningless in our case)
 * 2 - Write (input to the kernel module)
 * 4 - Read (output from the kernel module)
 *
 * This is the real function that checks file
 * permissions. The permissions returned by ls -l are
 * for referece only, and can be overridden here.
 */
static int module_permission(struct inode *inode, int op, struct nameidata *foo)
{
        /*
         * We allow everybody to read from our module, but
         * only root (uid 0) may write to it
         */
        if (op == 4 || (op == 2 && current->euid == 0))
                return 0;

        /*
         * If it's anything else, access is denied
         */
        return -EACCES;
}

/*
 * The file is opened - we don't really care about
 * that, but it does mean we need to increment the
 * module's reference count.
 */
int procfs_open(struct inode *inode, struct file *file)
{
        try_module_get(THIS_MODULE);
        return 0;
}

/*
 * The file is closed - again, interesting only because
 * of the reference count.
 */
int procfs_close(struct inode *inode, struct file *file)
{
        module_put(THIS_MODULE);
        return 0;               /* success */
}

 

static struct file_operations File_Ops_4_Our_Proc_File = {
        .read    = procfs_read,
        .write   = procfs_write,
        .open    = procfs_open,
        .release = procfs_close,
};


/*
 * Inode operations for our proc file. We need it so
 * we'll have some place to specify the file operations
 * structure we want to use, and the function we use for
 * permissions. It's also possible to specify functions
 * to be called for anything else which could be done to
 * an inode (although we don't bother, we just put
 * NULL).
 */

static struct inode_operations Inode_Ops_4_Our_Proc_File = {
        .permission = module_permission,        /* check for permissions */
};

 

/*
 * Module initialization and cleanup
 */
int init_module()
{
        /* create the /proc file */
        Our_Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL);

        /* check if the /proc file was created successfuly */
        if (Our_Proc_File == NULL){
                printk(KERN_ALERT "Error: Could not initialize /proc/%s/n",
                       PROC_ENTRY_FILENAME);
                return -ENOMEM;
        }

        Our_Proc_File->owner = THIS_MODULE;
        Our_Proc_File->proc_iops = &Inode_Ops_4_Our_Proc_File;
        Our_Proc_File->proc_fops = &File_Ops_4_Our_Proc_File;
        Our_Proc_File->mode = S_IFREG | S_IRUGO | S_IWUSR;
        Our_Proc_File->uid = 0;
        Our_Proc_File->gid = 0;
        Our_Proc_File->size = 80;

        printk(KERN_INFO "/proc/%s created/n", PROC_ENTRY_FILENAME);

        return 0;       /* success */
}

void cleanup_module()
{
        remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
        printk(KERN_INFO "/proc/%s removed/n", PROC_ENTRY_FILENAME);
}

原创粉丝点击