block(块),page(页),buffer cache(块缓冲区)之间的关系

原文地址:https://blog.csdn.net/menogen/article/details/32701457

关于blok vs page 的可以参考以下一段描述:

Storing Blocks in the Page Cache

In old versions of the Linux kernel, there were two different main disk caches: the page cache, which stored whole pages of disk data resulting from accesses to the contents of the disk files, and the buffer cache, which was used to keep in memory the contents of the blocks accessed by the VFS to manage the disk-based filesystems. Starting from stable version 2.4.10, the buffer cache does not really exist anymore. In fact, for reasons of efficiency, block buffers are no longer allocated individually; instead, they are stored in dedicated pages called “buffer pages,” which are kept in the page cache.Formally, abuffer pageis a page of data associated with additional descriptors called “buffer heads,” whose main purpose is to quickly locate the disk address of each individual block in the page. In fact, the chunks of data stored in a page belonging to the page cache are not necessarily adjacent on disk.

在 内存页中,有一种叫专门用途的页面叫“缓冲区页”,用来放块缓冲区。而每个块缓存区由两部分组成:缓冲区首部(用数据结构buffer_head表示)及真正的缓冲区内容(即所存储的数据,存放在缓冲区页中)。在缓冲区首部中,有一个指向数据的指针和一个缓冲区长度的字段。
每个缓冲区与一个块对应,它相当于磁盘块在内存中的表示。文件在内存中由file结构体表示,而磁盘块在内存中是由缓冲区来进行表示的。由于内核处理块时需要一些信息,如块属于哪个设备与块对应于哪个缓冲区,所以每个缓冲区都有一个缓冲区描述符,称为buffer_head,它包含了内核操作缓冲区所需要的全部信息。

struct buffer_head {

    unsigned long b_state;        /* buffer state bitmap (see above) *缓冲区的状态标志/

    struct buffer_head *b_this_page;/* circular list of page's buffers *页面中缓冲区/(一般一个页面会有多个块组成,一个页面中的块是以一个循环链表组成在一起的,该字段指向下一个缓冲区首部的地址。)

    struct page *b_page;        /* the page this bh is mapped to *存储缓冲区的页面/(指向拥有该块的页面的页面描述符)

    sector_t b_blocknr;        /* start block number *逻辑块号/

    size_t b_size;            /* size of mapping *块大小/

    char *b_data;            /* pointer to data within the page *指向该块对应的数据的指针/

    struct block_device *b_bdev;       //对应的块设备(通常是指磁盘或者是分区)

    bh_end_io_t *b_end_io;        /* I/O completion */

     void *b_private;        /* reserved for b_end_io *I/O完成的方法/

    struct list_head b_assoc_buffers; /* associated with another mapping */

    struct address_space *b_assoc_map;    /* mapping this buffer is associated with *缓冲区对应的映射,即address_space/

    atomic_t b_count;        /* users using this buffer_head *表示缓冲区的使用计数/

};

buffer_head中有两个字段表示块的磁盘地址:b_bdev表示包含该块的块设备(通常是磁盘或者分区)及b_blocknr存放逻辑块号,也就是块在磁盘或分区中的编号,b_data字段表示块缓冲区数据在缓冲区页中的位置。b_state存放缓冲区的状态,例如BH_uptodate(缓冲区包含有效数据时候被置位),Bh_Dirty(缓冲区脏就置位),BH_New(如果相应的块刚被分配而还没被访问过就置位)。

只要内核必须单独访问一个块,就要涉及存放块缓冲区中的缓冲区页,并检查相应的buffer_head

一个应用实例:如果虚拟文件系统要读1024个字节的inode 块,内核并不是只分配一个单独的缓冲区,而是必须分配一整个页,从而存放4个缓冲区(假设页大小4k),这些缓冲区将存放块设备上相邻的四块数据。它们之间的关系如下:(假定一个块是1K ,一个页是4K )。
在这里插入图片描述
在一个缓冲页内所有块缓冲区大小必须相同,因此,在80X86体系结构上,根据块的小大,一个缓冲区页可以包括1~8个缓冲区。如果一个页作为缓冲区页使用,那么与它的块缓冲区相关的所有缓冲区首部都被收集在一个单向循环链表中。page的private字段指向野种第一个块的buffer_head,每个buffer_head存放在b_this_page字段中,该字段是指向链表中的下一个缓冲区首部的指针。此外,每个buffer_head还把page的地址存放在b_page字段中,如上图所示。

猜你喜欢

转载自blog.csdn.net/qq_41688455/article/details/84761811