2012回首嵌入式学习两年历程

It's incredible,not impossible

伪文件系统bdev

整理了下伪文件系统bdev:


 517static struct file_system_type bd_type = {
 518        .name           = "bdev",
 519        .get_sb         = bd_get_sb,
 520        .kill_sb        = kill_anon_super,
 521};
 522
 523static struct vfsmount *bd_mnt __read_mostly;
 524struct super_block *blockdev_superblock;


这三个是文件系统的代表成员。文件系统类型、挂载点和超级块。

下面这个函数,应该是bdev文件系统的初始化函数:

1、为bdev_inode结构体创建slab缓存:kmem_cache_create

2、把文件系统类型注册进系统:register_filesystem








说下系统启动的时候,伪文件系统的启动流程:

start_kernel

vfs_caches_init

bdev_cache_init

所以这个函数就是伪文件系统的初始过程,我们也可以看到,在系统启动的时候,伪文件系统已经启动起来了。

 493void __init bdev_cache_init(void)
 494{
 495        int err;
 496        struct vfsmount *bd_mnt;
 497
 498        bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
 499                        0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
 500                                SLAB_MEM_SPREAD|SLAB_PANIC),
 501                        init_once);
 502        err = register_filesystem(&bd_type);
 503        if (err)
 504                panic("Cannot register bdev pseudo-fs");
 505        bd_mnt = kern_mount(&bd_type);
 506        if (IS_ERR(bd_mnt))
 507                panic("Cannot create bdev pseudo-fs");
 508        /*
 509         * This vfsmount structure is only used to obtain the
 510         * blockdev_superblock, so tell kmemleak not to report it.
 511         */
 512        kmemleak_not_leak(bd_mnt);
 513        blockdev_superblock = bd_mnt->mnt_sb;   /* For writeback */
 514}


kern_mount是挂载文件系统的函数,按道理,我们的伪文件系统bdev是无法挂载的阿。

架构p450:

内核提供了装载标志MS_NOUSER,防止此类文件系统被装载。

所有的文件系统机制,都适用于伪文件系统。

内核可以调用1804#definekern_mount(type)kern_mount_data(type,NULL)

这两个函数来“挂载”bdev文件系统。

(架构P443

通常意义上的挂载(用户空间的)会调用

sys_mount->do_mount->do_new_mount->

-->>vfs_kern_mount把文件系统集成到VFS中去
-->>graft_tree
把文件系统的文件和目录集成到用户可见的表示中



我们这里伪文件系统bdev会通过上面提到的两个函数,调用vfs_kern_mount,把自身集成到vfs中去,供内核使用。但是它调用graft_tree的时候,因为设置了装载标志位MS_NOUSER,所以这个函数什么都不干。

文件系统的使用

这样以来,伪文件系统就初始化好了。一个挂载的文件系统对应三个全局变量:

523staticstructvfsmount*bd_mnt__read_mostly;

524structsuper_block*blockdev_superblock;

517staticstructfile_system_typebd_type= {

考虑到两点:

1、一种类型的文件系统,在系统中可能同时存在多种。比如说/目录和/home目录可能都挂载了ext3类型的文件系统,在内存中存在的文件系统类型变量却是只有一个的。
2
、一个块设备,对应着一个超级块,可以挂载在多个目录上。

超级块对应的是一个块设备,对应这结构体supter_block

一个文件系统挂载一次,对应着一个结构体vfs_mount



所以我们不可以使用这两个结构体来操作我们欲操作的文件系统

523staticstructvfsmount*bd_mnt__read_mostly;

517staticstructfile_system_typebd_type= {

当我们查找一个文件系统的文件的时候,或者添加,或者删除文件,(本质上都是操作inode),我们都是以超级块来标志我们要操作的文件系统的。

524structsuper_block*blockdev_superblock;



bdev文件系统这就创建好了,我们下面需要知道两点:

1、他内部的节点是什么时候创建的bdev文件系统中的节点。

2、我们什么时候访问,和如何访问里面的节点。

其实内核中使用了这么一种机制:把查找和创建做成了一个接口,可能很多时候在创建的时候都需要判断是否已经存在,所以他很多东西的创建都是以查找函数为接口的,当查找不到的时候,再创建他,反正查找和创建返回的是一个东西。



目前我知道的踪迹是这个:(这个是创建的时候)

add_disk->

register_disk->

bdget_disk->

bdget(设备号)->

 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}


 571        inode = iget5_locked(bd_mnt->mnt_sb, hash(dev),
 572                        bdev_test, bdev_set, &dev);

 577        bdev = &BDEV_I(inode)->bdev;


看到这里两个东西,我们知道了,571这个必然是创建了一个inode,一个block_device,一个bdev_inode(后面这两个要跟到源码中看下)

因为577这个bdev本质上就等效是bdev =bdev_inode->block_device。借助container_of(inode)这个宏来实现的效果。

所以可以看到,我们的代表整个硬盘的block_device是这个时候被创建的。

下一步来研究我们每个分区的block_device是什么时候创建的。







阅读更多
个人分类: 2011 LDD
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭