MINIX - 磁盘块和缓冲块

磁盘块和缓冲块

README

  • 作者:邢万里
  • 学校:重庆邮电大学
  • email:wlxing@yahoo.com
  • 基于内核Linux 0.12源码

磁盘块

术语解释

  1. 定义:
    磁盘块表示磁盘上存储数据的地方,也就是数据真正存放的地方。即使电脑关机、文件保存等情况发生,磁盘块即是数据最终写入的位置(磁盘块的数据不会丢失,除非意外操作或者磁盘损坏等无法避免的情况)。
  2. 磁盘块==盘块==逻辑块==数据块
     a. 数据块,字面意思为存放数据的位置,但是这里(在Linux0.12中表示的只是磁盘中的一部分数据,不包括引导块、超级块、位图和i节点等)为下面第一张图的数据区部分。
     b. 逻辑块,定义为存储在磁盘或者磁带上的数据块(和磁盘块相同)。

存储、关联和读写

  1. MINIX文件系统在磁盘上的真正存放布局:
    磁盘块表示图中的数据区部分,在磁盘块前面有8块(1024字节),分别是引导块、超级块、位图和i节点。第一块盘块在超级块的成员s_firstdatazone表示,其值为8。注意,盘块号是包括前面8块在内计算,计算方式即为:block = nr + s_firstdatazone - 1; block即为盘块号,nr为位图中的索引(见“位图与磁盘关联方式”部分)。
  2. i节点与磁盘块的关联方式:
    通过i节点的成员i_zone数组,表示逻辑块的存放方式是由直接块、一次间接块和二次间接块构成。这基本的三部分均表示的是磁盘块,不是缓冲块,其存储的数据是盘块号。通过文件的i节点就能对应到相应的磁盘块号,再对应具体的磁盘块。
  3. 位图与磁盘块的关联方式:
    通过超级块的成员s_zmap数组,其成员b_data指针指向一块为1024字节的区域。s_zmap数组为struct buffer_head类型,代表的缓冲头部,由该头部进行指引作用,s_zmap的成员b_data指向一个缓冲区,缓冲区的每一位用0或者1表示,每一位依次按照盘块的顺序代表盘块是否正在使用,如果正在使用则表示1,否则为0。位图是缓冲块,顺序从0计数(特殊:s_zmap[0]的第一个位不用),所以如果对应到磁盘的计算过程即为,nr = block - s_firstdatazone + 1;block即为盘块号,nr即为位图(从0开始计数)的第nr个位置。再次注意:盘块号是从8开始计数(因为有8块在磁盘块前),而位图是从0开始计数。
  4. 磁盘块的读写方式:ll_rw_block()函数。
    通过设置该函数的第一个参数为write或read等,判断系统需要读取还是写入数据。
     a. 读取磁盘块过程(bread()函数):确定磁盘块号block–>获得与block和dev相关的缓冲块bh-->ll_rw_block(READ,bh)
     b. 写入磁盘块过程(sync_dev()函数):确定设备号dev–>找到相应的缓冲块bh-->ll_rw_block(WRITE,bh)
    注:
  5. “i节点与磁盘块的关联方式”是磁盘与磁盘的真实存在的关联方式。i节点成员i_zone数组保存的内容是盘块号。
  6. “位图与磁盘块的关联方式”是内存(缓冲块)与磁盘的关联方式。位图保存的内容是逻辑块是否占用。但通过求出某块在位图的偏移地址,再通过公式block = nr + s_firstdatazone - 1即能求出盘块号。由于位图的限制,一个文件最大能表示8 x 8 x 1024 bit为64MB。

缓冲块

术语解释
注: 请反复注意词汇“cache是缓存”和“buffer是缓冲”!
1. cache是高速缓存,用于CPU和内存之间的缓存。
2. buffer是I/O缓冲,用于内存和硬盘的缓冲。
3. 英文解释,如下:

“ A buffer is something that has yet to be “written” to disk. A cache is something that has been “read” from the disk and stored for later use. ”

  1. cache缓存是集成于CPU中,是介于CPU与主内存间的一种容量较小但速度很高的存储器。目的是为了打破内存读写速度慢的问题,减少了CPU的等待时间,提高了系统的效率。

  2. buffer缓冲是用于暂时存放数据,不同于磁盘块。当机器关机后,缓冲块数据清除,因此不是数据真正存放的位置。缓冲块占用的是内存,用于保护硬盘或减少网络传输的次数。同时也可以提高速度(不会立即写入硬盘或直接从硬盘中读出的数据马上显示),重复使用,最初最主要的目的是保护磁盘。【注意:和高速缓存(cache)区别!】如下图可知,buffer是物理内存的一部分(而高速缓存是CPU一部分)。

  3. 缓冲块头部==缓冲区头部==缓冲头,是指的struct buffer_head结构体,用于指引到具体的缓冲块位置,其结构如下(b_data指向缓冲块):

struct buffer_head {
        char * b_data;  /* pointer to data block (1024 bytes) */
        unsigned long b_blocknr;    /* block number */
        unsigned short b_dev;       /* device (0 = free) */
        unsigned char b_uptodate;
        unsigned char b_dirt;       /* 0-clean,1-dirty */
        unsigned char b_count;      /* users using this block */
        unsigned char b_lock;       /* 0 - ok, 1 -locked */
        struct task_struct * b_wait;
        struct buffer_head * b_prev;
        struct buffer_head * b_next;
        struct buffer_head * b_prev_free;
        struct buffer_head * b_next_free;
};

布局、关联和检索

  1. 高速缓冲区的布局:低端部分是struct buffer_head,弧线箭头是b_data指针,高端部分是具体的缓冲块部分。

  2. 空闲缓冲块的关联方式:通过缓冲头的成员b_prev_free和b_next_free指针进行关联,构建双向循环链表,再由缓冲头寻找具体的缓冲块。

  3. 缓冲块的关联/检索方式:通过缓冲头的成员b_prev和b_next指针进行关联,构建hash表,再由缓冲头寻找具体的缓冲块。

易混淆函数(block系列)

bitmap.c

  1. free_block()new_block()均是对磁盘上的数据块进行操作。一个是将磁盘上某块的数据全部失效(指没有人使用它),一个是将磁盘块新分配(指给特定设备使用)。

buffer.c

  1. getblk()的返回值是返回相应的缓冲块,作用为根据设备号和盘块号获取相应的缓冲块。其参数中的block是盘块号。

truncate.c

  1. free_ind()free_dind()truncate()函数均是对磁盘上数据操作,即为磁盘块。truncate()函数根据i节点的成员i_zone,找到对应的缓冲块头部,通过头部的成员b_data找到对应的缓冲块(其中是以0/1表示的位图),继而根据位图对磁盘上相应的磁盘块进行截断,截断文件后的长度为0,意味着该文件的数据全部失效。

技巧

  1. 关注参数名称是否为block,如果是,则参数为磁盘块号。
  2. 关注函数返回值是否是struct buffer_head,如果是则函数作用是寻找一个缓冲块。
  3. 一般寻找或者释放缓冲块都是需要由dev设备号和block盘块号进行定位。
  4. (注)只要记住这3条原则,就不会混淆了。

参考

  1. Linux内核完全剖析(基于0.12内核)赵炯–>第12章节。
  2. buffer与cache之间的区别:http://blog.chinaunix.net/uid-24020646-id-2939696.html
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Wanli_Xing/article/details/51991677
个人分类: MINIX Linux内核
想对作者说点什么? 我来说一句

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

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