我正在深入研究内核源代码,我注意到了这个函数set_bh_page()
。但是,我无法清楚地了解它的作用。
我只能在fs/buffer.c
文件中找到此评论:
/ *将缓冲区链接到其页面* /
set_bh_page(bh,page,offset);
但我仍然不清楚它的作用。
所以,为了说清楚,我想了解这个函数调用与缓冲区和物理页面之间的关系,以及它是否与页面缓存本身有关。
更新1:
函数alloc_page_buffers()
调用此set_bh_page()
,对此有一些评论,如下所示:
当给定数据区的页面和每个缓冲区的大小时,创建适当的缓冲区。用户bh-> b_this_page链表来跟踪创建的缓冲区。如果无法创建更多缓冲区,则返回NULL。
我检查了谁调用alloc_page_buffers()
,其中一个是read_page()
,有这样的描述:
从文件中读取页面。
我们都读取了页面,并将缓冲区附加到页面以记录每个块的地址(使用bmap)。这些地址将用于稍后写入块,完全绕过文件系统。这种用法类似于处理交换文件的方式,并允许我们写入文件而不用担心内存分配失败。
因此,通过浏览read_page()
的源代码,我的理解是分配的buffer_head
必须与其物理页面地址相关联,就像直接映射一样。
这是对的吗?
答案 0 :(得分:1)
当内核需要从块设备访问块并且它发现页面缓存中没有包含该块的页面时,它会分配一个页面,称为块设备缓冲页面或者只是一个缓冲页面,然后将所请求的块写入其中。该过程从grow_buffers函数开始,该函数调用alloc_page_buffers,其声明如下:
struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size, bool retry);
page
指向要保存块的缓冲区页面的描述符。 size
表示块的大小(以字节为单位),其中缓冲区页面的所有块都具有相同的大小。注意,块是块设备的存储区域,而缓冲区是主存储器的存储区域。缓冲区保存单个块的数据,并且它具有相同的大小。所以缓冲页面如下所示:
.
.
.
|-------------|
| buffer |
|-------------|
| buffer |
|-------------|
| buffer |
|-------------|
.
.
.
每个缓冲区中包含的块由缓冲区头标识。您可以找到buffer_head here的结构声明。 b_bdev
和b_blocknr
字段一起标识块设备上的块。请注意,每个缓冲区头都有一个指向同一缓冲区页面中下一个缓冲区头的指针。 alloc_page_buffers
函数分配并初始化指定缓冲区页面的所有缓冲区的缓冲区头。 alloc_page_buffers
调用set_bh_page
函数初始化缓冲区头的两个特定字段b_page
和b_data
,这些字段由代码中的注释描述:
struct page *b_page; /* the page this bh is mapped to */
char *b_data; /* pointer to data within the page */
正如您所看到的,它将缓冲区链接到其页面"。