18 缓冲区初始化buffer init:面试高频考点
你好,我是闪客。
在上一讲中我们说到了进程调度的初始化,让操作系统随时准备迎接时钟中断的到来,进而触发进程调度。
那接下来我们就回到 main 函数,继续看下一个初始化的方法,缓冲区初始化 buffer_init,加油,没剩多少了!
首先要注意到,这个函数传了个参数 buffer_memory_end,这个是在老早之前就设置好的,就在 第12讲 | 边界值划分与主内存初始化,可以去回顾下。

同时,且我们在 第12讲,主内存初始化 mem_init 中,用 mem_init 设置好了主内存的管理结构 mam_map。

这是把主内存区管理起来了,所以今天就是把剩下的缓冲区部分,也初始化管理起来。目的就是这么单纯,我们看代码。
我们还是采用之前的方式,就假设内存只有 8M,把一些不相干的分支去掉,方便理解。
// fs/buffer.c
extern int end;
struct buffer_head * start_buffer = (struct buffer_head *) &end;
void buffer_init(long buffer_end) {
struct buffer_head * h = start_buffer;
void * b = (void *) buffer_end;
while ( (b -= 1024) >= ((void *) (h+1)) ) {
h->b_dev = 0;
h->b_dirt = 0;
h->b_count = 0;
h->b_lock = 0;
h->b_uptodate = 0;
h->b_wait = NULL;
h->b_next = NULL;
h->b_prev = NULL;
h->b_data = (char *) b;
h->b_prev_free = h-1;
h->b_next_free = h+1;
h++;
}
h--;
free_list = start_buffer;
free_list->b_prev_free = h;
h->b_next_free = free_list;
for (int i=0;i<307;i++)
hash_table[i]=NULL;
}
虽然很长,但其实就造了两个数据结构而已。
不过别急,我们先从第一行代码开始看起。
// fs/buffer.c
extern int end;
void buffer_init(long buffer_end) {
struct buffer_head * start_buffer = (struct buffer_head *) &end;
...
}
这里有个外部变量 end,而我们的缓冲区开始位置 start_buffer 就等于这个变量的内存地址。
这个外部变量 end 并不是操作系统代码写就的,而是由链接器 ld 在链接整个程序时设置的一个外部变量,帮我们计算好了整个内核代码的末尾地址。