linux在被bootloader加载到内存后, cpu最初执行的linux内核代码是/header.S文件中的start_of_setup函数,这个函数在做了一些准备工作后会跳转到boot目下文件main.c的main函数执行,在这个main函数中我们可以第一次看到与内存管理相关的代码,这段代码调用detect_memeory()函数检测系统物理内存在header.S中执行下面汇编代码:
- start_of_setup:
- .....
- # Jump to C code (should not return)
- calll main
- .....
跳到boot目录下的main.c文件中
- void main(void)
- {
- ......
- /* Detect memory layout */
- detect_memory();/*内存探测函数*/
- ......
- }
- int detect_memory(void)
- {
- int err = -1;
-
- if (detect_memory_e820() > 0)
- err = 0;
-
- if (!detect_memory_e801())
- err = 0;
-
- if (!detect_memory_88())
- err = 0;
-
- return err;
- }
由上面的代码可知,linux内核会分别尝试调用detect_memory_e820()、detcct_memory_e801()、detect_memory_88()获得系统物理内存布局,这3个函数内部其实都会以内联汇编的形式调用bios中断以取得内存信息,该中断调用形式为int 0x15,同时调用前分别把AX寄存器设置为0xe820h、0xe801h、0x88h,关于0x15号中断有兴趣的可以去查询相关手册。下面分析detect_memory_e820()的代码,其它代码基本一样。
- #define SMAP 0x534d4150 /* ASCII "SMAP" */
- /*由于历史原因,一些i/o设备也会占据一部分内存
- 物理地址空间,因此系统可以使用的物理内存空
- 间是不连续的,系统内存被分成了很多段,每个段
- 的属性也是不一样的。int 0x15 查询物理内存时每次
- 返回一个内存段的信息,因此要想返回系统中所有
- 的物理内存,我们必须以迭代的方式去查询。
- detect_memory_e820()函数把int 0x15放到一个do-while循环里,
- 每次得到的一个内存段放到struct e820entry里,而
- struct e820entry的结构正是e820返回结果的结构!而像
- 其它启动时获得的结果一样,最终都会被放到
- boot_params里,e820被放到了 boot_params.e820_map。
- */
- static int detect_memory_e820(void)
- {
- int count = 0;/*用于记录已检测到的物理内存数目*/
- struct biosregs ireg, oreg;
- struct e820entry *desc = boot_params.e820_map;
- static struct e820entry buf; /* static so it is zeroed */
-
- initregs(&ireg);/*初始化ireg中的相关寄存器*/
- ireg.ax = 0xe820;
- ireg.cx = sizeof buf;/*e820entry数据结构大小*/
- ireg.edx = SMAP;/*标识*/
- ireg.di = (size_t)&buf;/*int15返回值的存放处*/
-
- /*
- * Note: at least one BIOS is known which assumes that the
- * buffer pointed to by one e820 call is the same one as
- * the previous call, and only changes modified fields. Therefore,
- * we use a temporary buffer and copy the results entry by entry.
- *
- * This routine deliberately does not try to account for
- * ACPI 3+ extended attributes. This is because there are
- * BIOSes in the field which report zero for the valid bit for
- * all ranges, and we don"t currently make any use of the
- * other attribute bits. Revisit this if we see the extended
- * attribute bits deployed in a meaningful way in the future.
- */
-
- do {
- /*在执行这条内联汇编语句时输入的参数有:
- eax寄存器=0xe820
- dx寄存器=’SMAP’
- edi寄存器=desc
- ebx寄存器=next
- ecx寄存器=size
-
- 返回给c语言代码的参数有:
- id=eax寄存器
- rr=edx寄存器
- ext=ebx寄存器
- size=ecx寄存器
- desc指向的内存地址在执行0x15中断调用时被设置
- */
- intcall(0x15, &ireg, &oreg);
- /*选择下一个*/
- ireg.ebx = oreg.ebx; /* for next iteration... */
-
- /* BIOSes which terminate the chain with CF = 1 as opposed
- to %ebx = 0 don"t always report the SMAP signature on
- the final, failing, probe. */
- if (oreg.eflags & X86_EFLAGS_CF)
- break;
-
- /* Some BIOSes stop returning SMAP in the middle of
- the search loop. We don"t know exactly how the BIOS
- screwed up the map at that point, we might have a
- partial map, the full map, or complete garbage, so
- just return failure. */
- if (oreg.eax != SMAP) {
- count = 0;
- break;
- }
-
- *desc++ = buf;/*将buf赋值给desc*/
- count++;/*探测数加一*/
- }
- while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map));
- /*将内存块数保持到变量中*/
- return boot_params.e820_entries = count;
- }
Linux物理内存描述RedHat Enterprise Linux 5安装Hyper-V的集成驱动(支持网络适配器 )相关资讯 Linux基础教程
- Linux基础教程:对文件打包压缩 (03月08日)
- 基础教程:Linux 新手应该知道的 (09/06/2015 21:17:20)
- Linux基础教程:find 与 xargs (04/05/2015 10:20:11)
| - Linux基础教程:tar 命令使用介绍 (12/03/2015 13:19:47)
- Linux基础教程(1)操作系统基础 (08/15/2015 20:44:01)
- Linux基础教程:从源码安装软件 (04/05/2015 10:14:45)
|
本文评论 查看全部评论 (0)