Linux文件系统 devfs/udev/sysfs简述

因为字符设备和块设备都很好的体现了“一切都是文件”的设计思想,所以了解掌握Linux文件系统,设备文件系统就显得很重要了。于是从重新简单的整理了一下 Linux文件系统 devfs/udev/sysfs 等三个系统的特点与联系。

devfs文件系统

按照时间顺序,devfs(设备文件系统)是由Linux2.4内核引入的,当时被许多工程师基于了高度的评价,devfs的出现使得设备驱动程序能够自主的管理自己的设备文件。比如,可以通过程序在设备初始化的时候在 /dev 目录下创建设备文件,卸载时将他删除,而且设备驱动程序可以指定设备名,所有者和权限位,而且用户空间程序可以修改所有者和权限位,并且不再需要为设备驱动程序分配主设备号以及次设备号,在程序中可以直接给 register_chrdev()传递0主设备号用来获取可用的主设备号。并且可以在 devfs_register() 中指定次设备号。
使用devfs的例子如下:

static devfs_handle_t devfs_handle;
static int __init xxx_init(void)
{
int ret;
int I;
/*在内核中注册设备*/
ret = register_chrdev(XXX_major, DEVICE_NAME, &xxx_fops);
if( ret < 0)
{
   printk(DEVICE_NAME “ can’t register major number\n”);
   return ret;
}
/*创建设备文件*/
devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT, xxx_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &xxx_fops, NULL);
…
printk(DEVICE_NAME “ initialized\n”);
return 0;
}

static void __exit xxx_exit(void)
{
devfs_unregister(devfs_handle);/*撤消设备文件*/
unregister_chrdev(XXX_MAJOR, DEVICE_NAME);/*注销设备*/
}

module_init(xxx_init);
module_exit(xxx_exit);

udev文件系统

尽管devfs 有这样那样的优点,但是在Linux2.6内核中,devfs被认为是过时的方法,并最终被抛弃,udev取代了它。udev 完全在用户态工作,利用设备加入或移除时内核所发送的热拔插时间来工作,在热拔插时,设备的详细信息会由内核同过netlink套接字发送出来,发送的事情叫uevent,另外一中情况是对于已经插入的设备,在开机的时候就已经插入的设备,称为冷拔插设备,对于冷拔插设备,Linux内核提供了sysfs下面一个uevent节点,可以往该节点写一个“add”,使得内核重新发送netlink套接字,之后udev就可以接收到冷拔插设备的netlink消息了。udev 和 devfs的另一个显著的区别在于,当采用devfs时候,当一个并不存在的/dev 结点被打开的时候,devfs会自动的加载对应的驱动,而udev则不能这么做,这是因为udev的设计者认为Linux应该在设备被发现的时候加载驱动模块,而不是当他被访问的时候,udev的设计者认为devfs所提供的打开 /dev结点时自动加载驱动的功能对于一个配置正确的计算机来说是多余的,系统中的所有设备都应该产生热拔插事件而不是加载恰当的驱动。
使用udev的例子如下:

#include <linux/device.h>
…

static struct class * xxx_class;

static int __init xxx_init(void)

{

int ret;
int i;

/*在内核中注册设备*/
ret = register_chrdev(XXX_major, DEVICE_NAME, &xxx_fops);

if( ret < 0)
{
   printk(DEVICE_NAME “ can’t register major number\n”);
   return ret;
}

//注册一个类,使mdev可以在"/dev/"目录下面建立设备节点
xxx_class = class_create(THIS_MODULE, DEVICE_NAME);

if(IS_ERR(led_class))
{
   printk("Err: failed in EmbedSky-leds class. \n");
   return -1;
}

//创建一个设备节点,节点名为DEVICE_NAME
class_device_create(xxx_class, NULL, MKDEV(xxx_major, 0), NULL, DEVICE_NAME);
…
printk(DEVICE_NAME “ initialized\n”);
return 0;
}

static void __exit xxx_exit(void)
{
unregister_chrdev(XXX_MAJOR, DEVICE_NAME);/*注销设备*/
class_device_destroy(xxx_class, MKDEV(xx_major, 0));//删掉设备点
class_destroy(xxx_class);               //注销类
}

module_init(xxx_init);
module_exit(xxx_exit);

sysfs文件系统

同样由于 devfs 文件系统不确定的设备映射关系,有时一个设备映射的设备文件可能不同,例如U盘有可能对应sda,又有可能对应sdb。并且没有足够的主/次设备号,当设备过多的时候,就会出现问题,另外 /dev目录下的文件太多而且不能表示当前系统上的实际设备。因此引入了一个新的文件系统 sysfs文件系统,是用来对系统的设备进行管理的,它可以产生一个包括所有系统硬件的层级视图,与提供进程和状态信息的proc文件系统十分相似。把实际连接到系统上的设备和总线组织成一个分级的文件,用户空间的程序同样可以利用这些信息以实现和内核的交 互,该文件系统是当前系统上实际设备树的一个直观反应,它是通过kobject子系统来建立这个信息的。想要了解sysfs文件系统 就要先了解一下linux设备模型,我在另一篇文章中简单的说过,地址是:https://blog.csdn.net/LinuxArmbiggod/article/details/78815859

总线、驱动、设备最终都会落实为sysfs中的一个目录,他们三个都可以认为是kobject的派生类,kobject可以看做是所有总线、设备和驱动的抽象基类,一个kobject对应一个sysfs中的一个目录。

猜你喜欢

转载自blog.csdn.net/LinuxArmbiggod/article/details/84137584