block(块),page(页),buffer cache(块缓冲)区别与联系

来源:互联网 发布:ubuntu安装有道词典 编辑:程序博客网 时间:2024/06/08 02:29

在自己的理解里,块就是用来管理磁盘空间的,就像我们在给一个磁盘建立文件系统时候,我们可以指定block_size,而页是针对内存管理,例如从磁盘读出的数据就缓存在内存页中,但突然对关buffer cache,block buffer 这些东西迷糊了,我们又说读出的数据放在内存页里边,但我们在内核代码中看到读出的每个block会对应一个由buffer_head管理的block buffer里边,那么,究竟读出的数据是放在什么的呢, page 跟block buffer又是什么关系呢??

关于blokc  vs page 的可以参考page size disk block size,What is the difference between pages and blocks?,blocksize vs page size,但是没解决我疑惑的答案。后来随着对内核源码的进一步学习 及参考 understanding the linux kernel ,逐渐明白了一些;

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. 它包含了内核操作缓冲区所需要的全部信息。

<span style="font-size:14px;">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 *表示缓冲区的使用计数/};</span>

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

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

一个应用实例:如果虚拟文件系统要读1024个字节的inode 块,内核并不是只分配一个单独的缓冲区,而是必须分配一整个页,从而存放4个缓冲区(假设页大小4k),这些缓冲区将存放块设备上相邻的四块数据。其中红包含所轻轻的inode块

他们之间的关系如下:(假定一个块是1K ,一个页是4K )


 在一个缓冲页内所有块缓冲区大小必须相同,因此,在80X86体系结构上,根据块的小大,一个缓冲区页可以包括1~8个缓冲区。如果一个页作为缓冲区页使用,那么与它的块缓冲区相关的所有缓冲区首部都被收集在一个单向循环链表中。page的private字段指向野种第一个块的buffer_head,每个buffer_head存放在b_this_page字段中,该字段是指向链表中的下一个缓冲区首部的指针。此外,每个buffer_head还把page的地址存放在b_page字段中,整个图如上所示。

完成!



0 0
原创粉丝点击