首页 > 其他 > 详细

/proc下文件创建的学习

时间:2015-10-17 19:18:16      阅读:293      评论:0      收藏:0      [点我收藏+]

    proc文件系统是一个伪文件系统;最初的设计目的是提供内核和用户交互的平台,使用户可以动态的管理系统,同时获取系统的运行时的信息。在proc中主要的信息便是系统进程信息.


1. proc_dir_entry结构体介绍


在/proc目录下创建文件,必然会用到proc_dir_entry结构体,其定义如下:

struct proc_dir_entry {
     unsigned int low_ino;              //目录项的inode索引节点号,唯一,proc_register_dynamic动态分配
     unsigned short namelen;               //name的长度
     const char *name;                  //node节点的name
     mode_t mode;                      //节点的类型type和权限permissions
     nlink_t nlink;                      //节点的链接数,初始化如果mode includes S_IFDIR为2,否则为1
     uid_t uid;                          //节点owns的uid、gid、size
     gid_t gid;                         
     loff_t size;
     const struct inode_operations *proc_iops;
     const struct file_operations *proc_fops;
     struct proc_dir_entry *next, *parent, *subdir;      //兄弟、父亲、子文件指针,parent一般设置为NULL,为/proc
     void *data;                           
     read_proc_t *read_proc;              //指向read_proc函数的指针
     write_proc_t *write_proc;          //指向write_proc函数的指针
     atomic_t count;                      /* use count */
     int pde_users;                      /* number of callers into module in progress */
     spinlock_t pde_unload_lock;         /* proc_fops checks and pde_users bumps */
     struct completion *pde_unload_completion;
     struct list_head pde_openers;         /* who did ->open, but not ->release */
};

const struct inode_operations *proc_iops;  
//  索引节点操作,描述了与 索引节点inode对象关联的方法 ,该结构的地址存放在inode结构体域变量i_op字段中,inode_operatons结构体定义在fs.h文件中

const struct file_operations *proc_fops;  
//定义了文件系统操作proc时的结构体指针,包含有read、write等函数;

当proc系统定义了自己的file_operations( proc_file_operations)时需要定义自己的读写函数:
        read_proc_t *read_proc;
        write_proc_t *write_proc;   
这两个函数提供了对proc文件进程操作的简单接口,通过其就可以就可以实现对一些功能简单的proc文件的读写操作,而不需要调用系统的file_operations结构(使用起来比较麻烦)。

proc文件自己的read、write函数原型定义如下:

typedef    int (read_proc_t)(char *page, char **start, off_t off,
             int count, int *eof, void *data);
typedef    int (write_proc_t)(struct file *file, const char __user *buffer,
             unsigned long count, void *data);

参数含义:
   buf:是从驱动层向应用层返回的数据区;当有用户读此/proc/xxx的文件时,由系统分配一页的缓存区,驱动使用read_proc此写入数据。
   start: 表示写在此页的哪里,此用法复杂,如果是返回小量数据(不超过一页)赋值为NULL。
   offset:与read用法一致,表示文件指针的偏移。
   count:与read用法一致,表示要读多少个字节。
   eof:  输出参数。
   data:由驱动内部使用。
   return: 返回值是可读到的字节数。

   
struct proc_dir_entry *next, *parent, *subdir;               //兄弟、父亲、子文件指针,parent一般设置为NULL,为/proc,目录树如下图所示:

技术分享

2. proc文件系统的初始化

    查看Proc_fs.h源码可以发现,在使用/proc文件系统前,需要先使其初始化:
    void proc_root_init(void); //初始化proc文件系统,定义在root.c文件中,大概定义了如图几个信息:

技术分享

int __init proc_init_inodecache(void)
//为proc_inode创建slab cache,这是proc文件系统的主要部分,通常需要快速创建或销毁。


int register_filesystem(struct file_system_type * fs)
//注册文件系统类型proc,这个过程是文件系统初始化的关键步骤

kern_mount_data(&proc_fs_type, &init_pid_ns)   //proc文件系统的挂在信息

proc_net_init();           //初始化与网络相关的文件目录等信息

proc_mkdir("driver", NULL);      //创建/proc目录下的子目录sysvipc、fs、driver、fs/nfsd、openprom、bus等

3. 创建proc目录下的文件

使用create_proc_entry()函数创建文件,函数定义如下:

struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
                     struct proc_dir_entry *parent)
{
    struct proc_dir_entry *ent;
    nlink_t nlink;

    if (S_ISDIR(mode)) {                   //判断是否为目录,目录链接=2
        if ((mode & S_IALLUGO) == 0)      //按位与,判断UGO是否有suid、sgid、rwx等权限,若没有,给它赋予RX权限
            mode |= S_IRUGO | S_IXUGO;      //按位或,S_IRUGO | S_IXUGO的结果再与mode按位或,结果赋值给mode
        nlink = 2;
    } else {
        if ((mode & S_IFMT) == 0)          //判断是否为文件
            mode |= S_IFREG;                //不是文件,设置为普通文件
        if ((mode & S_IALLUGO) == 0) 
            mode |= S_IRUGO;              //权限设为UGO可读
        nlink = 1;                      //链接=1
    }

    ent = __proc_create(&parent, name, mode, nlink); //创建文件或目录
    if (ent) {
        if (proc_register(parent, ent) < 0) { //创建成功,注册,这块使用默认的proc_file_operations
            kfree(ent); //释放ent
            ent = NULL;
        }
    }
    return ent;
}

参数:
        name:为要创建的文件名
        mode:为创建文件的权限
        parent:为创建文件的父目录,一般设置为NULL即就是/proc

截取proc_register()函数中部分代码如下:

static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{
    ......
    if (S_ISDIR(dp->mode)) {
        if (dp->proc_iops == NULL) {
            dp->proc_fops = &proc_dir_operations;
            dp->proc_iops = &proc_dir_inode_operations;
        }
        dir->nlink++;
    } else if (S_ISLNK(dp->mode)) {
        if (dp->proc_iops == NULL)
            dp->proc_iops = &proc_link_inode_operations;
    } else if (S_ISREG(dp->mode)) {
        if (dp->proc_fops == NULL)
            dp->proc_fops = &proc_file_operations;
        if (dp->proc_iops == NULL)
            dp->proc_iops = &proc_file_inode_operations;
    }
 ......
}

从中可以发现该函数中调用了proc自定义的proc_file_operations函数:

static const struct file_operations proc_file_operations = {
    .llseek        = proc_file_lseek,
    .read        = proc_file_read,
    .write        = proc_file_write,
};

因此在使用create_proc_entry函数创建文件时,就可以直接的使用proc自定义的文件操作的proc_read、proc_write函数,实现更简单。

继续查看Proc_fs.h文件发现create_proc_read_entry也可以创建文件,和create_proc_entry函数没有本质区别,只不过在定义时就指定了创建后的文件使用read_proc_t *read_proc,即使用proc自定义的文件操作函数,其定义如下:

static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
    mode_t mode, struct proc_dir_entry *base, 
    read_proc_t *read_proc, void * data)
{
    struct proc_dir_entry *res=create_proc_entry(name,mode,base);
    if (res) {
        res->read_proc=read_proc;
        res->data=data;
    }
    return res;
}

4. 删除创建的文件

    remove_proc_entry(const char *name, struct proc_dir_entry *parent);
    删除创建的文件,
       name为文件名;
       parent指向上级目录,为NULL时,默认为/proc目录


本文出自 “划舞鱼” 博客,请务必保留此出处http://ty1992.blog.51cto.com/7098269/1703794

/proc下文件创建的学习

原文:http://ty1992.blog.51cto.com/7098269/1703794

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!