18 缓冲区初始化buffer init:面试高频考点

你好,我是闪客。

在上一讲中我们说到了进程调度的初始化,让操作系统随时准备迎接时钟中断的到来,进而触发进程调度。

那接下来我们就回到 main 函数,继续看下一个初始化的方法,缓冲区初始化 buffer_init,加油,没剩多少了!

// init/main.c
void main(void) {
    ...
    buffer_init(buffer_memory_end);
    ...
}

首先要注意到,这个函数传了个参数 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 在链接整个程序时设置的一个外部变量,帮我们计算好了整个内核代码的末尾地址。