12.管理内存前先划分出三个边界值

12.管理内存前先划分出三个边界值

上回书咱们回顾了一下 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);    
    ...
}

是如何折腾的了。

那我们今天就不背着这两个负担了,仅仅需要知道这三个参数的计算,以及后面是为谁效力的,就好啦,是不是很轻松?后面我们再讲,如何利用这三个参数,来做到内存的管理。

updatedupdated2024-05-102024-05-10