书自<深入理解linux内核架构>:P449 解释下伪文件系统
文件系统未必要底层块设备支持,他们可以
1,使用内存作为后备存储器,比如ramfs 和tmpfs,
2,或者根本不需要后备存储器,比如 procfs 和sysfs,
这两种文件系统和传统观念已经有所不同了,但是还可以更进一步,上面两种文件系统有一个共性,那就是他们在用户空间是可见的,以文件和目录的形式出现.
3,伪文件系统 是不能装载的文件系统,是不可能能从用户空间看见的.(不能装载是用户空间看不见的原因)
如果文件系统无法向用户于导出任何东西,那么它能乍什么呢?虽然文件和目录的确是文件系统内容的一种可能而且是非常有用的一种表示,担不是唯一的表示.纯粹从inode的角度来看一个文件系统,也是可以的. 如此看来,文件和目录仅仅是文件系统的前端而已,乎略文件和目录不会带来任何的信息损失.
从这里也可以看出来,文件系统本身是对数据的管理手段和方式,目录和文件不过是为了用户(尤其是图形用户)看的,如果看不到,不等于他不存在.
在一些情况下,可能需要在内核内部把inode集群起来,而用户层无须知道这一点.但是以文件系统的形式建立这样的集合,内核可以从中受益,因为所有的标准辅助函数都能够处理通常的文件系统,现在当然也可以处理这样的集合.
伪文件系统的例子包括 1)负责管理块设备inode的bdev;2)负责处理管道的pipefs;3)处理套接字的sockfs; 这些都出现在 /proc/filesystems中.
伪文件系统,不能装载,当然这个不能指的是无法在用户空层 像普通文件系统那样装载 mount -t bdev bdev /mnt/bdev 这样会报错
QQ:待确认:
普通文件系统的装载完成两件事: 1)调用 do_kern_mount(调用vfs_kern_mount)把自己集成到VFS中 2)调用graft_tree把文件和目录集成到用户可见的表示中.
而伪文件系统只是调用kern_mount或者kern_mount_data(两者都调用vfs_kern_mount)把文件系统的数据集成到VFS中,如果调用gratf_tree,会因为装载标志位是MS_NOUSER而失败.
记住一点就够了,伪文件系统对于内核来说,就是一个普通的文件系统,按通用方法来使用即可,对于用户来说,他不存在.
架构P330
裸块设备由struct block_device来表示。
按照惯例,内核将与块设备关联的block_device实例紧邻块设备的inode之前存储。本行为由以下数据结构实现:
28 29struct bdev_inode { 30 struct block_device bdev; 31 struct inode vfs_inode; 32};
所有表示块设备的inode都保存在伪文件系统 bdev中,这些对用户层不可见。这使得可以使用标准的VFS函数,来处理块设备inode。
特别的,bdget就是利用了这一点,给定一个dev_t表示的设备号,该函数查找伪文件系统,看对应的inode是否已经存在,
如果存在,则返回该设备的block_device指针。
如果不存在,说明本设备之前没有被打开过,致使对应的inode尚未存在,bdget和伪文件系统会确保自动分配一个新的bdev_inode并进行适当的设置。
566struct block_device *bdget(dev_t dev) 567{ 568 struct block_device *bdev; 569 struct inode *inode; 570 571 inode = iget5_locked(bd_mnt->mnt_sb, hash(dev), 572 bdev_test, bdev_set, &dev); 573 574 if (!inode) 575 return NULL; 576 577 bdev = &BDEV_I(inode)->bdev; 578 579 if (inode->i_state & I_NEW) { 580 bdev->bd_contains = NULL; 581 bdev->bd_inode = inode; 582 bdev->bd_block_size = (1 << inode->i_blkbits); 583 bdev->bd_part_count = 0; 584 bdev->bd_invalidated = 0; 585 inode->i_mode = S_IFBLK; 586 inode->i_rdev = dev; 587 inode->i_bdev = bdev; 588 inode->i_data.a_ops = &def_blk_aops; 589 mapping_set_gfp_mask(&inode->i_data, GFP_USER); 590 inode->i_data.backing_dev_info = &default_backing_dev_info; 591 spin_lock(&bdev_lock); 592 list_add(&bdev->bd_list, &all_bdevs); 593 spin_unlock(&bdev_lock); 594 unlock_new_inode(inode); 595 } 596 return bdev; 597}