新读者看这里,老读者直接跳过。
本系列会以一个读小说的心态,从开机启动后的代码执行顺序,带着大家阅读和赏析 Linux 0.11 全部核心代码,了解操作系统的技术细节和设计思想。
你会跟着我一起,看着一个操作系统从啥都没有开始,一步一步最终实现它复杂又精巧的设计,读完这个系列后希望你能发出感叹,原来操作系统源码就是这破玩意。
书接上回,上回书我们说到了进程调度的初始化,定义了一个长度为 64 的 task 数组用于管理全部进程的结构。
那接下来我们就冷静下,回到 main 函数,继续看下一个初始化的过程。 那就是缓冲区初始化 buffer_init,加油,没剩多少了!
复制
void main(void) {
...
mem_init(main_memory_start,memory_end);
trap_init();
blk_dev_init();
chr_dev_init();
tty_init();
time_init();
sched_init();
buffer_init(buffer_memory_end);
hd_init();
floppy_init();
sti();
move_to_user_mode();
if (!fork()) {
init();
}
for(;;) pause();
}
再想不起来那就需要把前面的章节再读一读咯,不然后面越来越难。 前面是把主内存区管理起来了,所以今天就是把剩下的缓冲区部分,也初始化管理起来。目的就是这么单纯,我们看代码。 我们还是采用之前的方式,就假设内存只有 8M,把一些不相干的分支去掉,方便理解。
复制
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;
}
虽然很长,但其实就造了两个数据结构而已。
不过别急,我们先看这一行代码。
复制
extern int end;
void buffer_init(long buffer_end) {
struct buffer_head * start_buffer = (struct buffer_head *) &end;
...
}
这里有个外部变量 end,而我们的缓冲区开始位置start_buffer 就等于这个变量的内存地址。
这个外部变量 end 并不是操作系统代码写就的,而是由链接器 ld 在链接整个程序时设置的一个外部变量,帮我们计算好了整个内核代码的末尾地址。 那在这之前的是内核代码区域肯定不能用,在这之后的,就给 buffer 用了。所以我们的内存分布图可以更精确一点了。
大型站长资讯类网站! https://www.0817zz.com