sysfs/procfs/debugfs简介

来源:互联网 发布:信号与噪声算法 编辑:程序博客网 时间:2024/04/29 19:36

转自http://blog.csdn.net/rikeyone/article/details/51801298

Linux内核提供了三种内存文件系统,分别是sysfs、debugfs、procfs,驱动工程师可以通过任意的一种文件系统向用户空间传递信息。

Sysfs的挂载点为/sysDebugfs的挂载点为/sys/kernel/debugProcfs的挂载点为/proc

这三种形式的文件系统都是内存文件系统,他们中的信息只存在于内存中,下电后即消失。他们的出现旨在提供一种与用户空间交互信息的方式。

这三种类型文件系统的实现在内核中的:/kernel/fs/目录下。

如何使用它们呢? 
Sysfs 
我们知道在进行驱动注册时,对于一个驱动文件的生成,我们两个步骤:

1.调用cdev_add函数注册,函数的作用主要是把file_operations与dev的设备号关联起来。2.要调用device_create(&class, …)生成相对应的/sysfs目录和/dev设备文件。需要一个传入class和所需要的设备号。

device_create函数内部会调用到device_add函数,这个函数是生成设备文件的关键,实质上它是整个设备模型注册的关键。在device_add函数需要传入参数struct device,会在/sys/device目录下生成相应的sys文件,同时会判断device结构中的devt变量是否可用,如果可用才会调用devtmpfs_create_node(dev);在/dev目录下生成对应的设备文件。所以说device_add是否会生成设备文件需要根据device结构体中是否传入了设备号来决定的。 
由上所写,除了调用device_create来生成对应的设备文件以外,我们也可以自己初始化device结构体后调用device_add函数来生成设备文件。

如: 
evdev->dev.devt = MKDEV(INPUT_MAJOR, minor); 
evdev->dev.class = &input_class; 
evdev->dev.parent = &dev->dev; 
evdev->dev.release = evdev_free; 
device_initialize(&evdev->dev); 
cdev_init(&evdev->cdev, &evdev_fops); 
evdev->cdev.kobj.parent = &evdev->dev.kobj; 
error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); 
if (error) 
goto err_unregister_handle;

error = device_add(&evdev->dev);if (error)    goto err_cleanup_evdev;

evdev->cdev.kobj.parent = &evdev->dev.kobj;这一步的作用是在sysfs的该device目录中生成对应的dev文件。该文件内容就是设备号。

在驱动注册时调用device_create(&class, …)只会在sysfs中生成对应的一个设备目录,而我们更多的时候需要把一些驱动信息传递到用户层,这一步是通过在该目录中生成属性文件的方式来实现的。

接下来我们看看属性文件是怎么生成的。

1.device_create_file单个生成接口: 
针对struct device_attribute结构体,生成sysfs中的设备属性文件,可以使用下面的方法: 
int device_create_file ( struct device * dev, 
const struct device_attribute * attr); 
其中会调用到sysfs_create_file函数来生成sysfs属性文件,此接口用于生成单个属性文件。

2.sysfs_create_group批量生成接口: 
例如: 
首先定义struct device_attribute结构体,如果需要的属性为polling的话定义如下: 
static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR, show_polling, set_polling);

封装struct attribute结构体,注意成员变量是&dev_attr_polling.attr. 
static struct attribute *dev_attrs[] = { 
&dev_attr_polling.attr, 
NULL, 
}; 
.然后再封装成struct attribute_group 
static struct attribute_group dev_attr_grp = { 
.attrs = dev_attrs, 
}; 
在利用sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);创建接口

这里介绍了两种方法,当然除了这两种,你也可以提前静态的定义struct device_type,在struct device中赋值后调用device_add接口,来一次性生成设备目录和设备属性文件。

Procfs 
这种也比较简单,以一个例子来说明它的使用方法吧。

static int __init input_proc_init(void) 
{ 
struct proc_dir_entry *entry;

proc_bus_input_dir = proc_mkdir("bus/input", NULL);if (!proc_bus_input_dir)    return -ENOMEM;entry = proc_create("devices", 0, proc_bus_input_dir,            &input_devices_fileops);if (!entry)    goto fail1;entry = proc_create("handlers", 0, proc_bus_input_dir,            &input_handlers_fileops);if (!entry)    goto fail2;return 0;

fail2: remove_proc_entry(“devices”, proc_bus_input_dir); 
fail1: remove_proc_entry(“bus/input”, NULL); 
return -ENOMEM; 
}

Debugfs

Debugfs和procfs差不多,主要是用来调试时使用,这部分也没什么好讲的,大家参考gpio子系统中的实现自行研阅吧



0 0
原创粉丝点击