Linux 虚拟文件系统

1、常用虚拟文件系统

虚拟文件系统用于Linux内核和用户空间的数据交换。

(1)procfs — 提供内核数据结构的接口,挂载在/proc目录。procfs 历史最早,最初就是用来跟内核交互的唯一方式,用来获取处理器-即cpu、内存、设备驱动、进程等各种信息。

(2)sysfs — 导出内核对象,挂载在/sys目录。sysfs 跟 kobject 框架紧密联系, sysfs 是为设备驱动服务的。

mount -t sysfs sys_debug /data/

(3)debugfs — Debugfs exists as a simple way for kernel developers to make information available to user space。debugfs 从名字来看就是为debug而生,所以更加灵活。

mount -t debugfs kernel_debug /data/

(4)configfs —— 最新usb gadget 驱动采用此文件系统。

mount -t configfs config_debug /data/

(5)tracefs —— 用于跟踪Linux 自带log:如 trace_dwc3_gadget_ep_cmd

mount -t tracefs trace_debug /data/

1.1 configfs 和 sysfs

configfs是基于ram的文件系统,与sysfs的功能有所不同。
sysfs是基于文件系统的kernel对象视图,虽然某些属性允许用户读写,但对象是在kernel中创建、注册、销毁,由kernel控制其生命周期。
configfs是一个基于文件系统的内核对象管理器(或称为config_items),config_items在用户空间通过mkdir显式的创建,使用rmdir销毁,在mkdir之后会出现对应的属性,可以在用户空间对这些属性进行读写,与sysfs不同的是,这些对象的生命周期完全由用户空间控制,kernel只需要响应用户空间的操作即可。
configfssysfs两者可以共存,但不能相互取代。

2、sysfs

sysfs 最主要是用来描绘Linux kernel 2.6 中的设备驱动模型。

2.1 创建属性文件 device_create_file

创建属性文件节点的接口有4个:

sysfs_create_file    //通过kobject创建sysfs的节点(后面3个接口最终都会调用此接口,
							参数attr中没有读写操作的接口,所以不使用此接口)。
device_create_file   //为设备创建sys的节点。
bus_create_file     //为总线创建sys的节点。
driver_create_file   //为驱动创建sys的节点。

sysfs_create_group		//创建一个sysfs目录

实例1:

static int device_init(void)
{
	struct device *dbxiong_dev;
	dev_t dbxiong_devt = MKDEV(dbxiong_major,dbxiong_minor);	//创建设备号
	struct class *dbxiong_class;
	//创建设备类别目录:/sys/class/dbxiong_class
	dbxiong_class = class_create(THIS_MODULE,"dbxiong_class");
	
	//创建设备文件:/sys/class/dbxiong_class/dbxiong
	dbxiong_dev = device_create(dbxiong_class,NULL,dbxiong_devt,"dbxiong_drvdata","dbxiong");
	
	//创建属性文件:/sys/class/dbxiong_class/dbxiong/dbxiong_device
	device_create_file(dbxiong_dev,&dev_attr_dbxiong_device);
	return 0;
}

实例2:

//在dev 指向设备所在sys节点目录下创建test 属性文件,
//如/sys/devices/platform/soc/a600000.ssusb/mode(dev_attr_mode)
err = device_create_file(&dev->dev, &dev_attr_test);	
if (err) {
        dev_err(&dev->dev, "sys file creation failed\n");
        return -ENODEV;
}

static ssize_t test_show(struct device *dev,
                   struct device_attribute *attr, char *buf)
{

    int temp[3];
    struct test_data *gpio_data_ptr = dev_get_drvdata(dev);
    temp[0] = gpio_get_value(gpio_data_ptr->gpio0);
    temp[1] = gpio_get_value(gpio_data_ptr->gpio1);
    temp[2] = gpio_get_value(gpio_data_ptr->gpio2);

    return snprintf(buf, 4, "%d%d%d", temp[0], temp[1],
                    temp[2]);
}

static ssize_t test_store(struct device *dev,
           struct device_attribute *attr, const char *buf, size_t size)

{
    struct test *gpio_data_ptr = dev_get_drvdata(dev);
    gpio_set_value(gpio_data_ptr->gpio0,  (buf[0] == '1') ? 1 : 0);
    gpio_set_value(gpio_data_ptr->gpio1,  (buf[1] == '1') ? 1 : 0);
    gpio_set_value(gpio_data_ptr->gpio2,  (buf[2] == '1') ? 1 : 0)
    return size;
}

static DEVICE_ATTR(test, 0664, test_show, test_store);

2.1.1 class_create()

struct class *class_create(struct module *owner, const char *name) 

第一个参数指定类的所有者是哪个模块;
第二个参数指定类名。
如下:

misc_class = class_create(THIS_MODULE, "misc");

将会创建出 /sys/class/misc

2.1.2 device_create()

struct device *device_create(struct class *class, struct device *parent,
                        dev_t devt, const char *fmt, ...)

第一个参数指定所要创建的设备所从属的类;
第二个参数是这个设备的父设备,如果没有就指定为NULL;
第三个参数是设备号;
第四个参数是设备名称;
第五个参数是从设备号。
如下:

misc->this_device = device_create(misc_class, misc->parent, dev, misc, "%s", misc->name);

将会创建出一个文件夹/sys/class/misc/misc->name(如/sys/class/misc/gpio),同时加载模块的时候,用户空间中的udev 会自动响应 device_create()函数,去/sysfs下寻找对应的类从而创建设备节点(一个文件)/dev/misc->name(如/dev/gpio)。

3、udev

udev 就是利用了sysfs 提供的信息来实现所有devfs的功能的,但不同的是udev运行在用户空间中,而devfs却运行在内核空间。

用户态的后台程序(udev)会动态地周期性的扫描/sys目录中的属性项来自动管理设备文件(也称为设备节点),从而在/dev目录会建立或者删除对应的设备文件。

3.1 热拔插事件

udev 利用设备插入或拔出时内核所发出的热拔插事件(Hotplug Event)来工作。在热拔插时,设备的详细信息会由内核通过netlink 套接字发送出来,发出的事情叫做uevent

udev 从内核收到的信息来创建设备文件。

3.2 冷拔插事件

对于冷拔插的设备,Linux 内核提供了sysfs 下面一个uevent 节点,可以往该节点写一个“add”,导致内核重新发送netlink,之后udev 就可以收到冷拔插的netlink 消息了。

3.3 kobject

kobject 可看做是所有总线、设备和驱动的抽象基类,1个kobject 对应sysfs 中的一个目录总线、设备和驱动中的各个attribute 则对应sysfs 中的1个文件attribute 会伴随着show()store() 这两个函数,分别用于读写该attribute 对应的sysfs 文件。

sysfs 中的目录来源于bus_type, device_driver, device, 而目录中的文件则来源于attribute

sysfs中通过uevent机制来实现一个整个热插拔

uevent整个机制相对比较清晰,当有新的device产生时,kobjct产生uevent事件,通过两种方式通知到用户层netlinkuevent_helper,在用户空间种linux提供了两个机制一个是udev(user device)通过nelink接收uevent产生的事件,另外一种方式是通过uevent_helper,该方式主要是通过回调方式通知用户层。

struct device {
	struct kobject kobj;		//每个device都有一个kobj
	struct device		*parent;

	struct device_private	*p;

	const char		*init_name; /* initial name of the device */
	const struct device_type *type;

	struct bus_type	*bus;		/* type of bus device is on */
	struct device_driver *driver;	/* which driver has allocated this
					   device */
	void		*platform_data;	/* Platform specific data, device
					   core doesn't touch it */
	void		*driver_data;	/* Driver data, set and get with
					   dev_set_drvdata/dev_get_drvdata */
}
//调用实例
int device_add(struct device *dev)
{
	struct device *parent;
	struct kobject *kobj;
	
	parent = get_device(dev->parent);			//获取device 的parent
	kobj = get_device_parent(dev, parent);		//获取 parent 的kobj
	if (kobj)
		dev->kobj.parent = kobj;
	error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);	//add device的kobj到parent 下
	kobject_uevent(&dev->kobj, KOBJ_ADD);	//产生KOBJ_ADD 事件,通知给用户空间
}

4. linux 驱动生成文件节点

linux用户空间和kernel空间是分开,所以上层需要和某个模块驱动交流的时候,就需要驱动来创建一个文件节点。
以下三种方法,第一种和第二种方法使用时一般流程就是open、read/write、ioctl等,第三种方法则可以通过echo/cat命令来读写

4.1 /dev 节点

在这里插入图片描述

4.2 /proc 节点

在这里插入图片描述
在这里插入图片描述
上图中建的节点是/proc/onekey_recovery/last_pressed,如果不用proc_mkdir而只用proc_create的话,则生成的节点是/proc/last_pressed.

4.3 /sys 节点

使用DEVICE_ATTR,可以实现驱动在sys目录自动创建文件,我们只需要实现showstore 函数即可。然后在应用层就能通过cat和echo命令来对sys创建出来的文件进行读写驱动设备,实现交互。

#include <board.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
#include <sound/soc.h>
#include <sound/jack.h>


static  char mybuf[100]="123";
//cat命令时,将会调用该函数
static ssize_t show_my_device(struct device *dev,
         struct device_attribute *attr, char *buf)       
{
    return sprintf(buf, "%s\n", mybuf);
}

//echo命令时,将会调用该函数
static ssize_t set_my_device(struct device *dev,
                 struct device_attribute *attr,
                 const char *buf, size_t len)        
{
    sprintf(mybuf, "%s", buf);
    return len;
}
//定义一个名字为my_device_test的设备属性文件
static DEVICE_ATTR(my_device_test, S_IWUSR|S_IRUSR, show_my_device, set_my_device);
                
struct file_operations mytest_ops={
         .owner  = THIS_MODULE,
};

static int major;
static struct class *cls;
static int mytest_init(void)
{
struct device *mydev;   
major=register_chrdev(0,"mytest", &mytest_ops);
cls=class_create(THIS_MODULE, "mytest_class");
//创建mytest_device设备
mydev = device_create(cls, 0, MKDEV(major,0),NULL,"mytest_device");        
	//在mytest_device设备目录下创建一个my_device_test属性文件
    if(sysfs_create_file(&(mydev->kobj), &dev_attr_my_device_test.attr)){   
            return -1;
}
            
    	return 0;
}

static void mytest_exit(void)
{
         device_destroy(cls, MKDEV(major,0));
         class_destroy(cls);
         unregister_chrdev(major, "mytest");
}

module_init(mytest_init);
module_exit(mytest_exit);
MODULE_LICENSE("GPL");
 
  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
模拟Linux文件系统。在任一OS下,建立一个文件,把它假象成一张盘,在其中实现一个简单的 模拟Linux文件系统 在现有机器硬盘上开辟20M的硬盘空间,作为设定的硬盘空间。 2. 编写一管理程序对此空间进行管理,以模拟Linux文件系统,具体要求如下: (1) 要求盘块大小1k 正规文件 (2) i 结点文件类型 目录文件 (共1byte) 块设备 管道文件 物理地址(索引表) 共有13个表项,每表项2byte 文件长度 4byte 。联结计数 1byte (3)0号块 超级块 栈长度50 空闲盘块的管理:成组链接 ( UNIX) 位示图法 (Linux) (4)每建一个目录,分配4个物理块 文件名 14byte (5)目录项信息 i 结点号 2byte (6)结构: 0#: 超级块 1#-20#号为 i 结点区 20#-30#号为根目录区 3. 该管理程序的功能要求如下: (1) 能够显示整个系统信息,源文件可以进行读写保护。目录名和文件名支持全路径名和相对路径名,路径名各分量间用“/”隔开。 (2) 改变目录:改变当前工作目录,目录不存在时给出出错信息。 (3) 显示目录:显示指定目录下或当前目录下的信息,包括文件名、物理地址、保护码、文件长度、子目录等(带/s参数的dir命令,显示所有子目录)。 (4) 创建目录:在指定路径或当前路径下创建指定目录。重名时给出错信息。 (5) 删除目录:删除指定目录下所有文件和子目录。要删目录不空时,要给出提示是否要删除。 (6) 建立文件(需给出文件名,文件长度)。 (7) 打开文件(显示文件所占的盘块)。 (8) 删除文件:删除指定文件,不存在时给出出错信息。 4. 程序的总体流程为: (1) 初始化文件目录; (2) 输出提示符,等待接受命令,分析键入的命令; (3) 对合法的命令,执行相应的处理程序,否则输出错误信息,继续等待新命令,直到键入EXIT退出为止。
在任一OS下,建立一个文件,把它假象成一张盘,在其中实现一个简单的模拟Linux文件系统。 1. 在现有机器硬盘上开辟100M的硬盘空间,作为设定的硬盘空间。 2. 编写一管理程序simdisk对此空间进行管理,以模拟Linux文件系统,要求: (1) 盘块大小1k (2) 空闲盘块的管理:Linux位图法 (3) 结构:超级块, i结点区, 根目录区 3. 该simdisk管理程序的功能要求如下: (1) info: 显示整个系统信息(参考Linux文件系统的系统信息),文件可以根据用户进行读写保护。目录名和文件名支持全路径名和相对路径名,路径名各分量间用“/”隔开。 (2) cd …: 改变目录:改变当前工作目录,目录不存在时给出出错信息。 (3) dir …: 显示目录:显示指定目录下或当前目录下的信息,包括文件名、物理地址、保护码、文件长度、子目录等(带/s参数的dir命令,显示所有子目录)。 (4) md …: 创建目录:在指定路径或当前路径下创建指定目录。重名时给出错信息。 (5) rd …: 删除目录:删除指定目录下所有文件和子目录。要删目录不空时,要给出提示是否要删除。 (6) newfile …: 建立文件。 (7) cat …: 打开文件。 (8) copy …: 拷贝文件,除支持模拟Linux文件系统内部的文件拷贝外,还支持host文件系统与模拟Linux文件系统间的文件拷贝,host文件系统文件命名为…,如:将windows下D:盘的文件\data\sample\test.txt文件拷贝到模拟Linux文件系统中的/test/data目录,windows下D:盘的当前目录为D:\data,则使用命令: simdisk copy D:\data\sample\test.txt /test/data 或者:simdisk copy D:sample\test.txt /test/data (9) del …: 删除文件:删除指定文件,不存在时给出出错信息。 (10) check: 检测并恢复文件系统:对文件系统中的数据一致性进行检测,并自动根据文件系统的结构和信息进行数据再整理。 4. 程序的总体流程为: (1) 初始化文件目录; (2) 输出提示符,等待接受命令,分析键入的命令; (3) 对合法的命令,执行相应的处理程序,否则输出错误信息,继续等待新命令,直到键入EXIT退出为止。
1. 在现有机器硬盘上开辟100M的硬盘空间,作为设定的硬盘空间。 2. 编写一管理程序simdisk对此空间进行管理,以模拟Linux文件系统,要求: (1) 盘块大小1k (2) 空闲盘块的管理:Linux位图法 (3) 结构:超级块, i结点区, 根目录区 3. 该simdisk管理程序的功能要求如下: (1) info: 显示整个系统信息(参考Linux文件系统的系统信息),文件可以根据用户进行读写保护。目录名和文件名支持全路径名和相对路径名,路径名各分量间用“/”隔开。 (2) cd …: 改变目录:改变当前工作目录,目录不存在时给出出错信息。 (3) dir …: 显示目录:显示指定目录下或当前目录下的信息,包括文件名、物理地址、保护码、文件长度、子目录等(带/s参数的dir命令,显示所有子目录)。 (4) md …: 创建目录:在指定路径或当前路径下创建指定目录。重名时给出错信息。 (5) rd …: 删除目录:删除指定目录下所有文件和子目录。要删目录不空时,要给出提示是否要删除。 (6) newfile …: 建立文件。 (7) cat …: 打开文件。 (8) copy …: 拷贝文件,除支持模拟Linux文件系统内部的文件拷贝外,还支持host文件系统与模拟Linux文件系统间的文件拷贝,host文件系统文件命名为<host>…,如:将windows下D:盘的文件\data\sample\test.txt文件拷贝到模拟Linux文件系统中的/test/data目录,windows下D:盘的当前目录为D:\data,则使用命令: simdisk copy <host>D:\data\sample\test.txt /test/data 或者:simdisk copy <host>D:sample\test.txt /test/data (9) del …: 删除文件:删除指定文件,不存在时给出出错信息。 (10) check: 检测并恢复文件系统:对文件系统中的数据一致性进行检测,并自动根据文件系统的结构和信息进行数据再整理。 4. 程序的总体流程为: (1) 初始化文件目录; (2) 输出提示符,等待接受命令,分析键入的命令; (3) 对合法的命令,执行相应的处理程序,否则输出错误信息,继续等待新命令,直到键入EXIT退出为止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值