Linux内核源代码情景分析-设备文件系统devfs

本文探讨了Linux内核源代码中设备文件系统devfs的设计思想,指出传统设备号管理的不足,并提出devfs的理想特性,如层次结构、动态管理和与原有方案的兼容性。详细介绍了devfs的数据结构、安装过程以及设备驱动如何通过devfs_register(chrdev, blkdev)注册设备节点。" 110252473,7414383,ProtoBuf vs JSON:性能与内存比较,"['protobuf', 'json']
摘要由CSDN通过智能技术生成

    我们以前多次讲过到,以主设备号/次设备号为基础的设备文件管理方式是有根本性的缺点的。这种从Unix早期一直沿用下来的方案一方面给设备号的管理带来了麻烦,一方面也破坏了/dev目录结构。Unix/Linux系统中的所有目录的结构都是层次的,惟独/dev目录是"平面"的。这不光是风格的问题,也直接影响着访问的效率和管理的方便与否。

    那么理想中的/dev目录应该是什么样的呢?首先,它应该是层次的、树状的。其次,它的规模应该是可伸缩的,而且不受数量的限制(例如256个主设备号)。还有,/dev目录中的内容应该反映系统当前在设备驱动方面的实际情形。例如,这样一套方案就是比较理想的:

    1、系统加电之初/dev目录为空。

    2、系统在初始化阶段扫描并枚举所有连接着的设备,就像对PCI总线的扫描枚举一样。每找到一项设备就分门别类地在/dev目录下创建起子目录,然后以设备的序号作为最底层的节点名,例如"/dev/ide/hd/1",”/dev/ide/floppy/1“等等。

    3、以后,每插入一个设备,或安装一个可安装模块,就由内核在/dev子树中增加一个或几个节点。

    4、反之,如果关闭或拆除一个设备,或拆除一个可安装模块,就由内核在/dev子树中删去相应的节点。

    5、还得与原来的方案兼容。

    其实设备文件系统devfs,和特殊文件系统/proc思路基本一样。

    

    一、文件系统类型devfs_fs_type的定义如下:

static DECLARE_FSTYPE (devfs_fs_type, DEVFS_NAME, devfs_read_super, FS_SINGLE);
    经过gcc的编译预处理以后,就会成为如下的定义:
struct file_system_type devfs_fs_type = {
        name:       "devfs",
        read_super: devfs_read_super,
        fs_flags:   FS_SINGLE,
        owner:      THIS_MODULE,
}
    系统在初始化时会调用init_devfs_fs进行对devfs特殊文件系统的初始化,代码如下:

int __init init_devfs_fs (void)
{
    int err;

    printk ("%s: v%s Richard Gooch (rgooch@atnf.csiro.au)\n",
	    DEVFS_NAME, DEVFS_VERSION);
#ifdef CONFIG_DEVFS_DEBUG
    devfs_debug = devfs_debug_init;
    printk ("%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug);
#endif
    printk ("%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options);
    err = register_filesystem (&devfs_fs_type);//向系统登记文件系统类型devfs_fs_type
    if (!err)
    {
	struct vfsmount *devfs_mnt = kern_mount (&devfs_fs_type);//初始安装特殊文件系统devfs
	err = PTR_ERR (devfs_mnt);
	if ( !IS_ERR (devfs_mnt) ) err = 0;
    }
    return err;
}

struct vfsmount *kern_mount(struct file_system_type *type)
{
	kdev_t dev = get_unnamed_dev();
	struct super_block *sb;
	struct vfsmount *mnt;
	if (!dev)
		return ERR_PTR(-EMFILE);
	sb = read_super(dev, NULL, type, 0, NULL, 0);
	if (!sb) {
		put_unnamed_dev(dev);
		return ERR_PTR(-EINVAL);
	}
	mnt = add_vfsmnt(NULL, sb->s_root, NULL);
	if (!mnt) {
		kill_super(sb, 0);
		return ERR_PTR(-ENOMEM);
	}
	type->kern_mnt = mnt;//重点
	return mnt;
}
static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
				       struct file_system_type *type, int flags,
				       void *data, int silent)
{
	struct super_block * s;
	s = get_empty_super();
	if (!s)
		goto out;
	s->s_dev = dev;
	s->s_bdev = bdev;
	s->s_flags = flags;
	s->s_dirt = 0;
	sema_init(&s->s_vfs_rename_sem,1);
	sema_init(&s->s_nfsd_free_path_sem,1);
	s->s_type = type;
	sema
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值