linux用户\内核空间交互之:proc文件系统

10 篇文章 2 订阅

proc介绍

        proc文件系统是linux中的一个虚拟文件系统,内核运行时将内核中一些关键的数据结构以文件的方式呈现在/proc目录中的一些特定文件中,这样相当于将不可见的内核中的数据结构以可视化的方式呈现给开发者。我们通过观察/proc/xxx文件,可以直观的观察到一些特定的数据结构的值。

例如:

/proc/cpuinfo :处理器的相关信息的文件

/proc/cmdline:在启动时传递至内核的相关参数信息,这些信息通常由lilo或grub等启动管理工具进行传递

/proc/devices :系统已经加载的所有块设备和字符设备的信息,包含主设备号和设备组(与主设备号对应的设备类型)名

/proc/modules:标识了当前加载到内核中的模块

/proc/pci:显示当前在pci总线上能找到的设备

。。。

 

对proc中文件的读写操作方法

[root@admin]# cat /proc/sys/net/ipv4/ip_forward

0

[root@admin]# echo "1" > /proc/sys/net/ipv4/ip_forward

[root@admin]# cat /proc/sys/net/ipv4/ip_forward

1

[root@admin]#

        /proc 文件系统并不是 GNU/Linux 系统中的惟一一个虚拟文件系统。在这种系统上,sysfs 是一个与 /proc 类似的文件系统,但是它的组织更好(从 /proc 中学习了很多教训)。不过 /proc 已经确立了自己的地位,因此即使 sysfs 与 /proc 相比有一些优点,/proc 也依然会存在。还有一个 debugfs 文件系统,不过(顾名思义)它提供的更多是调试接口。debugfs 的一个优点是它将一个值导出给用户空间非常简单(实际上这不过是一个调用而已)。

 

创建/proc中目录

在/proc中创建一个目录,接收要创建的目录名,父目录的结构体指针,如果为空,就在/proc目录下创建一个目录

 struct proc_dir_entry *proc_mkdir( const char *name , struct proc_dir_entry *parent );

 

创建\删除 proc项

在/proc中创建一个虚拟文件,使用下面函数,接收一个文件名,一组权限,和这个文件在/proc文件系统中的位置。

//创建
//linux版本小于3.10.0使用该接口
struct proc_dir_entry *create_proc_entry( const char *name, mode_t mode,
                                             struct proc_dir_entry *parent );


//linux版本大于等于3.10.0使用该接口
struct proc_dir_entry *proc_create_data(const char *name, umode_t mode, struct             
                                        proc_dir_entry *parent,
                                const struct file_operations *proc_fops, void * data);

//删除
void remove_proc_entry( const char *name, struct proc_dir_entry *parent );



//还有一种方法创建proc文件,还没用过,但是方法类似
struct proc_dir_entry *proc_create(const char *name, mode_t mode, struct proc_dir_entry     
                                       *parent, const struct file_operations *proc_fops)

 proc_dir_entry结构体部分内容:

struct proc_dir_entry {

 

    const char *name;           // virtual file name

    mode_t mode;                // mode permissions

    uid_t uid;              // File's user id

    gid_t gid;              // File's group id

    struct inode_operations *proc_iops; // Inode operations functions

    struct file_operations *proc_fops;  // File operations functions

    struct proc_dir_entry *parent;      // Parent directory

    ...

    read_proc_t *read_proc;         // /proc read function

    write_proc_t *write_proc;       // /proc write function

    void *data;             // Pointer to private data

    atomic_t count;             // use count

    ...

};

proc_dir_entry 快捷变量

proc_dir_entry在文件系统中的位置
proc_root_fs/proc
proc_net/proc/net
proc_bus/proc/bus
proc_root_driver/proc/driver

 

其他proc创建函数

这个函数在procfs目录下创建一个从name指向dest的符号链接. 它在用户空间等效为ln -s dest name

struct proc_dir_entry *proc_symlink(const char *name, struct proc_dir_entry *parent, const char *dest)

 

读写回调函数

可以使用 write_proc 向 /proc 中写入数据。

也可以使用 read_proc 从一个 /proc 项中读出数据(内核空间到用户空间)

这两个函数原型如下:

int mod_write( struct file *filp, const char __user *buff,
               unsigned long len, void *data );


int mod_read( char *page, char **start, off_t off,
              int count, int *eof, void *data );

 

示例代码

#include <linux/module.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>


char str[]="this a text!";

static struct proc_dir_entry * test_entry = NULL;
static struct proc_dir_entry * test_root = NULL; 

static ssize_t  test_read(struct file * file,char __user *data,size_t len,loff_t *off)
{
        char *ptr = PDE_DATA(file_inode(file)); //获取proc_create_data传入的私有数据。
        printk("%s\n",ptr);
        printk("proc read。。。\n");
        return 0;
}

static ssize_t test_write(struct file * file,const char __user* data,size_t len,loff_t *off)
{
        printk("proc write。。。\n");
        return len;
}

static struct file_operations test_proc_ops = {
       .owner  = THIS_MODULE,
       .read = test_read, 
       .write = test_write
};

static int proc_init(void)
{
    proc_root = proc_mkdir("test_dir", NULL);
    test_entry = proc_create_data("test_node", 0666, proc_root, &test_proc_ops, &str);
         
    if(!test_entry){
        printk(KERN_ERR"can't create  proc file \n" );
        return -EFAULT;
    }
         
    return 0;
}


static void proc_exit(void)
{
    if(test_entry)
    {
        remove_proc_entry("test_node",proc_root);
    }
 
}

module_init(proc_init);
module_exit(proc_exit);

       procfs有一个缺陷,如果输出内容大于1个内存页,需要多次读,因此处理起来很难,另外,如果输出太大,速度比较慢,有时会出现一些意想不到的情况

       GUN/linux系统中还有一种虚拟文件系统是sys文件系统,和proc文件系统类似,但是组织更加友好,读/sys中的文件就是获取内核中数据结构的值,而写入/sys中的文件就是设置内核中的数据结构的元素的值。后续再专门再分析一下这个文件系统。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值