上回书咱们回顾了一下 main.c 函数之前我们做的全部工作,给进入 main 函数做了一个充分的准备。
那今天我们就话不多说,从 main 函数的第一行代码开始读。
还是把 main 的全部代码都先写出来,很少。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| void main(void) {
ROOT_DEV = ORIG_ROOT_DEV;
drive_info = DRIVE_INFO;
memory_end = (1<<20) + (EXT_MEM_K<<10);
memory_end &= 0xfffff000;
if (memory_end > 16*1024*1024)
memory_end = 16*1024*1024;
if (memory_end > 12*1024*1024)
buffer_memory_end = 4*1024*1024;
else if (memory_end > 6*1024*1024)
buffer_memory_end = 2*1024*1024;
else
buffer_memory_end = 1*1024*1024;
main_memory_start = buffer_memory_end;
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()) {
/* we count on this going ok */
init();
}
for(;;)
pause();
}
|
我们今天就看这第一小段。
首先,ROOT_DEV 为系统的根文件设备号,drive_info 为之前 setup.s 程序获取并存储在内存 0x90000 处的设备信息,我们先不管这俩,等之后用到了再说。
我们看后面这一坨很影响整体画风的一段代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| void main(void) {
...
memory_end = (1<<20) + (EXT_MEM_K<<10);
memory_end &= 0xfffff000;
if (memory_end > 16*1024*1024)
memory_end = 16*1024*1024;
if (memory_end > 12*1024*1024)
buffer_memory_end = 4*1024*1024;
else if (memory_end > 6*1024*1024)
buffer_memory_end = 2*1024*1024;
else
buffer_memory_end = 1*1024*1024;
main_memory_start = buffer_memory_end;
...
}
|
这一坨代码和后面规规整整的 xxx_init 平级的位置,要是我们这么写代码,肯定被老板批评,被同事鄙视了。但 Linus 写的,就是经典,学就完事了。
这一坨代码虽然很乱,但仔细看就知道它只是为了计算出三个变量罢了。
main_memory_start
memory_end
buffer_memory_end
而观察最后一行代码发现,其实两个变量是相等的,所以其实仅仅计算出了两个变量。
main_memory_start
memory_end
然后再具体分析这个逻辑,其实就是一堆 if else 判断而已,判断的标准都是 memory_end 也就是内存最大值的大小,而这个内存最大值由第一行代码可以看出,是等于 1M + 扩展内存大小。
那 ok 了,其实就只是针对不同的内存大小,设置不同的边界值罢了,为了理解它,我们完全没必要考虑这么周全,就假设总内存一共就 8M 大小吧。
那么如果内存为 8M 大小,memory_end 就是: 8 * 1024 * 1024
也就只会走倒数第二个分支,那么 buffer_memory_end 就为: 2 * 1024 * 1024
那么 main_memory_start 也为: 2 * 1024 * 1024
那这些值有什么用呢?一张图就给你说明白了。
你看,其实就是定了三个箭头所指向的地址的三个边界变量,具体主内存区是如何管理和分配的,要看下面代码的功劳。
1
2
3
4
5
| void main(void) {
...
mem_init(main_memory_start, memory_end);
...
}
|
而缓冲区是如何管理和分配的,就要看
1
2
3
4
5
| void main(void) {
...
buffer_init(buffer_memory_end);
...
}
|
是如何折腾的了。
那我们今天就不背着这两个负担了,仅仅需要知道这三个参数的计算,以及后面是为谁效力的,就好啦,是不是很轻松?后面我们再讲,如何利用这三个参数,来做到内存的管理。