免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1620 | 回复: 8
打印 上一主题 下一主题

/proc file system的读函数的疑问(问题在3楼,呵呵) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-03-17 11:23 |只看该作者 |倒序浏览
本帖最后由 pan_130421 于 2010-03-17 11:27 编辑

/**
* procfs2.c −   create a "file" in /proc
* sudo chmod 777 /proc/helloworld
*/
#include <linux/proc_fs.h>      /* Necessary because we use the proc fs */
#include "hello.h"

#define PROCFS_MAX_SIZE         1024
#define PROCFS_NAME             "helloworld"
/**
* This structure hold information about the /proc file
*
*/
static struct proc_dir_entry *Our_Proc_File;
/**
* The buffer used to store character for this module
*
*/
static char procfs_buffer[PROCFS_MAX_SIZE];
/**
* The size of the buffer
*
*/
static unsigned long procfs_buffer_size = 0;
/**
* This function is called then the /proc file is read
*
*/
int
procfile_read(char *buffer,
              char **buffer_location,
              off_t offset, int buffer_length, int *eof, void *data)
{
        int ret;
        printk(KERN_ALERT "procfile_read (/proc/%s) called\n", PROCFS_NAME);
        if (offset > 0) {
                /* we have finished to read, return 0 */
                ret = 0;
        } else {
                /* fill the buffer, return the buffer size */
                memcpy(buffer, procfs_buffer, procfs_buffer_size);
                ret = procfs_buffer_size;
        }
        return ret;
}
/**
* This function is called with the /proc file is written
*
*/
int procfile_write(struct file *file, const char *buffer, unsigned long count,
                    void *data)
{
        /* get buffer size */
        procfs_buffer_size = count;
        if (procfs_buffer_size > PROCFS_MAX_SIZE ) {
                procfs_buffer_size = PROCFS_MAX_SIZE;
        }
        /* write data to the buffer */
        if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
                return -EFAULT;
        }
        return procfs_buffer_size;
}
/**
*This function is called when the module is loaded
*
*/
int proc_init(void)
{
        /* create the /proc file */
        Our_Proc_File = create_proc_entry(PROCFS_NAME, 0644, NULL);
        if (Our_Proc_File == NULL) {
                remove_proc_entry(PROCFS_NAME, NULL);
                printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
                         PROCFS_NAME);
                return -ENOMEM;
        }
        Our_Proc_File->read_proc   = procfile_read;
        Our_Proc_File->write_proc  = procfile_write;
        //Our_Proc_File->owner       = THIS_MODULE;
        Our_Proc_File->mode        = S_IFREG | S_IRUGO;
        Our_Proc_File->uid         = 0;
        Our_Proc_File->gid         = 0;
        Our_Proc_File->size        = 1024;
        printk(KERN_ALERT "/proc/%s created\n", PROCFS_NAME);
        return 0;        /* everything is ok */
}
/**
*This function is called when the module is unloaded
*
*/
void proc_cleanup(void)
{
        remove_proc_entry(PROCFS_NAME, NULL);
        printk(KERN_ALERT "/proc/%s removed\n", PROCFS_NAME);
}

论坛徽章:
0
2 [报告]
发表于 2010-03-17 11:25 |只看该作者
/*
* procfs3.c − create a "file" in /proc, use the file_operation way
*              to manage the file.
*/
#include <linux/proc_fs.h>      /*  Necessary because we use proc fs */
#include <asm/uaccess.h>        /*  for copy_*_user */
#include "hello.h"
#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_ALERT "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_ALERT "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,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 proc_fop_init(void)
{
        /* 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_ALERT "/proc/%s created\n", PROC_ENTRY_FILENAME);
        return 0;        /* success */
}
void proc_fop_cleanup(void)
{
        remove_proc_entry(PROC_ENTRY_FILENAME, NULL);
        printk(KERN_ALERT "/proc/%s removed\n", PROC_ENTRY_FILENAME);
}

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
3 [报告]
发表于 2010-03-17 11:25 |只看该作者
Oops了吗

论坛徽章:
0
4 [报告]
发表于 2010-03-17 11:26 |只看该作者
我的问题是在1楼里面的代码,read函数可以用memcpy,而2楼里面的read为什么只能用copy_to_user?
难道1楼里面的没有用户指针和内核指针的区别吗?

请多多指教。

论坛徽章:
0
5 [报告]
发表于 2010-03-17 11:28 |只看该作者
Oops了吗
Godbach 发表于 2010-03-17 11:25



    OOPS ?

论坛徽章:
0
6 [报告]
发表于 2010-03-17 13:57 |只看该作者
回复 4# pan_130421


   一楼的的read都是在内核空间,二楼则是通过file_operations,所以才有你的疑问

论坛徽章:
5
摩羯座
日期:2014-07-22 09:03:552015元宵节徽章
日期:2015-03-06 15:50:392015亚冠之大阪钢巴
日期:2015-06-12 16:01:352015年中国系统架构师大会
日期:2015-06-29 16:11:2815-16赛季CBA联赛之四川
日期:2018-12-17 14:10:21
7 [报告]
发表于 2010-03-17 14:04 |只看该作者
稍微看了一下
两个read的性质不一样
一楼是kernel空间的copy
二楼是从user空间读kernel空间的buffer

论坛徽章:
5
摩羯座
日期:2014-07-22 09:03:552015元宵节徽章
日期:2015-03-06 15:50:392015亚冠之大阪钢巴
日期:2015-06-12 16:01:352015年中国系统架构师大会
日期:2015-06-29 16:11:2815-16赛季CBA联赛之四川
日期:2018-12-17 14:10:21
8 [报告]
发表于 2010-03-17 14:04 |只看该作者
稍微看了一下
两个read的性质不一样
一楼是kernel空间的copy
二楼是从user空间读kernel空间的buffer

论坛徽章:
0
9 [报告]
发表于 2010-03-18 16:34 |只看该作者
稍微看了一下
两个read的性质不一样
一楼是kernel空间的copy
二楼是从user空间读kernel空间的buffer
T-Bagwell 发表于 2010-03-17 14:04


谢谢两位指点。
但是还有疑问:
假设1楼的read是内核空间的copy,则write是也应该是在内核空间吧?
不考虑函数实现
procfs_read与procfs_write的参数 char *buffer不是同时指向用户区域吗?
怎么理解前者是内核空间,后者是用户空间呢?

当然,事实上这样编码是没有问题,只是想不明白。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP