EXT2文件系统笔记之ext2_fill_super

来源:互联网 发布:手机健身运动软件 编辑:程序博客网 时间:2024/05/23 00:04

-----------------------------------写在2017/05/29 13:56--------------------------------------------------------

周六答辩,最近无所事事,重新看以前自己写的笔记,心中颇有感慨,写上来吧,如果哪天笔记本丢了,所有的回忆也都没有了。其实我真的不是一个会写东西的人,学习过程中也很少写,因此遇到同样的问题时总是又要重新百度,Google,这其实不是一个很好的习惯。

声明:因为很久没有看了,所以可能有一些是错误的,有疑问的小伙伴可以提出问题,我看到的话会回答的哦。毕竟我也是在学习中的嘛。

其实,如果你们看到这里,我相信,你们应该是一个热爱学习充满好奇心的人,笔记基本都是关于EXT2的,EXT4是研三下学期才看的,EXT4相对于EXT2来说差别很大!!但是EXT2是基础,看源代码比较好理解。好啦废话不多说啦!开始咯!

-----------------------------------------------------关于文件系统部分的源代码我都有注释,可以去我的github 下载,对你有用的话,可以给我一个star 哦 哈哈谢谢------------------

-----------------------------------github地址:https://github.com/Hafy/linux-2.6.32.67-  ------------------------------------------------------------------

                -----------------------------------------------转载请注明出处--------------------------------------------------------

1、分配一个struct ext2_sb_info * sbi结构

2、因为不知道该设备的块大小是多少,因此不知道超级块所在的块号以及偏移量是多少。因此会有一个猜测,然后计算得到一个逻辑上的猜测的超级块所在的块号logic_sb_block

      (一)sb_bread函数解析

          调用sb_bread(sb, logic_sb_block)获得该逻辑块号所在的缓冲区首部 即buffer_head  下面我们来分析一下sb_bread函数

     最终会调用struct buffer_head *__bread(struct block_device *bdev, sector_t block, unsigned size)
{
struct buffer_head *bh = __getblk(bdev, block, size);


if (likely(bh) && !buffer_uptodate(bh))//buffer_uptodate(bh)==1表示该缓冲区存在有效数据  =0表示该缓冲区不存在有效数据
bh = __bread_slow(bh);//感觉是将磁盘上的相应的数据块读到上面的bh->b_data中
return bh;
}

分析struct buffer_head *__getblk(struct block_device *bdev, sector_t block, unsigned size)
{
struct buffer_head *bh = __find_get_block(bdev, block, size);


might_sleep();
if (bh == NULL)
bh = __getblk_slow(bdev, block, size);//页高速缓存中找不到该页则创建一页
return bh;
}

分析struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block, unsigned size)
{
struct buffer_head *bh = lookup_bh_lru(bdev, block, size);//该函数在lru链表 里找我们要的缓冲区首部


if (bh == NULL) {
bh = __find_get_block_slow(bdev, block);//找不到调用该函数在页高速缓冲区查找buffer head
if (bh)
bh_lru_install(bh);//将我们在页高速缓冲区中找到的该逻辑块对应的buffer  head结构加入到lru链表里面
}
if (bh)
touch_buffer(bh);
return bh;
}


关于__find_get_block总结:

  在lru->bhs[]数组中查找是否有目标块对应的bh(lru->bhs实际上是最近最常访问的bh的一个数组),如果找到,则将该block对应的bh移到lru->bhs[0]中,数组越前面表示是最新的访问的bh

如果在lru中没有找到,则调用bh = __find_get_block_slow(bdev, block);//找不到调用该函数在页高速缓冲区查找buffer head,如果在页高速缓冲区中找到目标block对应的bh,则调用bh_lru_install(bh);//将我们在页高速缓冲区中找到的该逻辑块对应的buffer  head结构加入到lru链表里面

如果在lru中与页高速缓冲区中都没有找到目标block对应的bh,则__find_get_block函数返回NULL.且调用_getblk_slow函数在页高速缓冲区中新建一个bh

分析static struct buffer_head *__getblk_slow(struct block_device *bdev, sector_t block, int size)

  该函数最终调用static int grow_buffers(struct block_device *bdev, sector_t block, int size)

 (1)通过block目标块号与块大小size计算该块对应的页的index 

(按照我的理解是该index应该是该块号所在的页索引号,比如block 为 0,1,2,3 则index=0,block为4,5,6,7该index=1,假如块大小是1024的话,一个page可以包含4个block)
 (2)到这一步时,block是形参的目标块号block对应的page的那四个block号的首个block号,也就是该page的偏移量为0的那个逻辑块号,比如如果index=1,则该该block=4

调用 page = grow_dev_page(bdev, block, index, size);

分析该函数:

           ① 在页高速中page = find_or_create_page(inode->i_mapping, index,(mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);新建一个page

           ② bh = alloc_page_buffers(page, size, 0);//分配4个buffer_head 连成一个链表,最后返回链表头的buffer_head

              每个bh->b_this_page指向下一个bh,且着四个bh=>b_data分别指向page->virtual ,page->virtual+1024,page->virtual+2018,page->virtual+3072 其实就是着四个bh对应                的page的虚拟地址,着四个bh的虚拟地址其实是连续的。

          ③link_dev_buffers(page, bh);//将buffer_head连成循环链表  ,将最后一个bh->b_this_page指回首个bh形成循环链表

          ④ init_page_buffers(page, bdev, block, size);//将和块号block在同一页的块号存进对应的bh->b_blocknr中

         ⑤成功返回 page

-----------------------------------sb_bread函数解析完了,继续--------------------------------

sbi->s_group_desc 是一个struct buffer_head ** s_group_desc;   接着刚刚的sb_bread

 计算得到该设备的块组描述符占据的块数目db_count后

//db_count是存储该文件系统的全部块组描述符需要的数据块数
//假设需要10块 循环10次将这10个数据块在页高速缓存中的对应的buffer_head对应的挂接到
//ext2_sb_info->s_group_desc[]数组中

--------------------------------------------别的我就不说了,主要就是填充超级块的结构。。额 感觉自己理解的不是很充分,因此写的也乱七八糟。。。。---------------------------

原创粉丝点击