linux-0.11分析:init文件 main.c的第一个初始化函数mem_int 第四篇随笔
init文件夹 mian.c
参考 [github这个博主的 厉害][ https://github.com/sunym1993/flash-linux0.11-talk ]
-
首先先看看这个
mian.c
中的主要几行代码吧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; #ifdef RAMDISK main_memory_start += rd_init(main_memory_start, RAMDISK*1024); #endif 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(); } /* 注意!!对于任何其他任务,“pause()”意味着我们必须获得一个 *发出唤醒信号,但task0是唯一的例外(请参阅“schedule()”) *因为任务0在每个空闲时刻被激活(当没有其他任务时 *可以运行)。对于task0,“pause()”只意味着我们去检查其他 *任务可以运行,否则我们返回这里 */ for(;;) pause(); }
-
首先看看前两行代码:
ROOT_DEV = ORIG_ROOT_DEV; 这是在设置系统根文件的设备号 drive_info = DRIVE_INFO; 这里是在设置之前存在0x90000位置处的设备信息
再看看这些设备信息吧
地址 | 字节 | 存储的东西 |
---|---|---|
0x90000 | 1 | 光标列号 |
0x90001 | 1 | 光标行号 |
0x90002 | 2 | 内存大小 |
0x90004 | 2 | 显示页面 |
0x90006 | 1 | 模式模式 |
0x90007 | 1 | 窗口宽度 |
0x90008 | 2 | 配置参数 |
0x9000A | 2 | 配置参数 |
0x9000C | 2 | 配置参数 |
0x90080 | 16 | hd0硬盘信息 |
0x90010 | 16 | hd1硬盘信息 |
-
接下来看看中间那段代码
memory_end = (1<<20) + (EXT_MEM_K<<10); memory_end &= 0xfffff000; if (memory_end > 16*1024*1024) //内存是否大于16MB memory_end = 16*1024*1024; //如果大于,就memory_end把置为16MB if (memory_end > 12*1024*1024) //内存是否大于12MB buffer_memory_end = 4*1024*1024;//如果大于,就把buffer_memory_end置为4MB else if (memory_end > 6*1024*1024) //内存是否大于6MB buffer_memory_end = 2*1024*1024;//如果大于,就buffer_memory_end把置为2MB else buffer_memory_end = 1*1024*1024;//如果都不满足,就buffer_memory_end把置为2MB main_memory_start = buffer_memory_end;//把buffer_memory_end值给main_memory_start #ifdef RAMDISK main_memory_start += rd_init(main_memory_start, RAMDISK*1024); //main_memory_start加上一段距离 #endif 仔细看会发现,这就是在定义,且改变这
memory_end、main_memory_start、buffer_memory_end
这三个变量的值;首先前面有句:#define EXT_MEM_K (*(unsigned short *)0x90002)
在获取
memory_end
的内存大小后面就是一些判断,判断内存的大小并初始化数据;代码有解释
实际上就是这三个变量
memory_end、main_memory_start、buffer_memory_end
指向了不同的位置我们用内存为16MB来说明,有一张图来说明一哈
-
看看后面那一段init(初始化)代码,先看第一个
mem_init
1、第一个初始化函数,mem_init
()
mem_init(main_memory_start,memory_end);
可以看出传入之前定义的那两个参数:main_memory_start、memory_end
mm 文件夹 memory.c
那先看看这个函数把:这个函数的位置在:linux文件下mm文件下的memory.c中
#define invalidate() \ __asm__("movl %%eax,%%cr3"::"a" (0)) /* these are not to be changed without changing head.s etc */ #define LOW_MEM 0x100000 #define PAGING_MEMORY (15*1024*1024) //15728640 #define PAGING_PAGES (PAGING_MEMORY>>12) //3840 #define MAP_NR(addr) (((addr)-LOW_MEM)>>12) #define USED 100 #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \ current->start_code + current->end_code) static long HIGH_MEMORY = 0; #define copy_page(from,to) \ __asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si") static unsigned char mem_map [ PAGING_PAGES ] = {0,}; //start_mem = 4MB end_mem = 16MB void mem_init(long start_mem, long end_mem) { int i; HIGH_MEMORY = end_mem; //前面定义:HIGH_MEMORY = 0 赋值为传入的参数end_mem for (i=0 ; i<PAGING_PAGES ; i++) //PAGING_PAGES前面也有 mem_map[i] = USED; //前面的定义的一个char数组 i = MAP_NR(start_mem); //MAP_NR前面定义了 start_mem这个位置减去LOW_MEM,再右移12位 end_mem -= start_mem; //更改传入的参数end_mem = end_mem - start_mem end_mem >>= 12; // end_mem右移动12位 while (end_mem-->0) mem_map[i++]=0; // }
如果传入的start_mem = 4MB end_mem = 16MB
-
HIGH_MEMORY = 4MB PAGING_PAGES = 3840B
正好一个char型占1个字节也就是8位 -
mem_map 数组的3840B全为100
-
i = 768B
-
end_mem = 3072B
-
mem_map数组 从 768B 开始全部添加3840B个0
-
使所以数组的长度为 3840 每个里面存4k数据的位置,正好为15MB
-
真相这些只是把数据存放在数组中,并不代表真实的内存
-
实际上就是
mem_map
数组存储哪些内存有值,哪些没有为0可以使用 -
最终就是 1-3MB为100值;3~16MB为0
-
正好
mem_map
数组的前768存100,768~3840存0
看看下面这个图吧
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)