Linux 0.11内存初始化:内存分块与管理分析

需积分: 0 0 下载量 178 浏览量 更新于2024-07-13 收藏 3.04MB PPT 举报
"内存初始化过程init/main.c-存储管理分析" 在Linux 0.11内核中,内存管理是一个至关重要的部分,它涉及到系统的稳定性和效率。内存初始化过程主要在`init/main.c`文件中进行,这个过程是操作系统启动过程中的一部分,用于设置和规划内存的使用布局。 内存初始化首先通过读取BIOS提供的信息来确定扩展内存的大小。扩展内存的实际大小以k为单位存储在地址0x90002开始的2字节中。计算内存结束地址`memory_end`时,会加上1MB的基础内存(即`(1<<20)`),然后加上扩展内存的大小`(EXT_MEM_K<<10)`。这样的设计确保了内存在物理地址空间中的正确位置。 为了简化内存管理和页的计算,操作系统会忽略不足4KB的内存块,通过将`memory_end`与`0xfffff000`进行按位与操作,使得内存大小对齐到4KB的页边界。这样做是因为内存管理通常是基于4KB页面进行的。 内存大小的限制设定在16MB,如果`memory_end`超过这个值,会被强制设为16MB,以防止超出硬件实际支持的范围。此外,根据内存大小的不同,系统会为缓冲区分配不同数量的空间: - 如果内存大于12MB,缓冲区`buffer_memory_end`分配4MB。 - 如果内存介于6MB和12MB之间,分配2MB。 - 否则,如果内存小于或等于6MB,分配1MB。 缓冲区主要用于文件系统,为文件缓冲机制提供存储空间。主内存区位于缓冲区之后,是新进程可以使用的内存区域,这部分内存由操作系统管理,包括分配和回收。 内存的这种布局设计使内核区、缓冲区、虚拟盘(如果有)和主内存区各司其职,确保了系统资源的有效利用。内核区存放内核代码,由于经常被调用,所以常驻内存。缓冲区为文件系统服务,提高文件操作的效率。虚拟盘(RAMDISK)是可选的,如果启用,会占用一部分内存作为虚拟磁盘使用。主内存区则是进程运行的舞台,其大小根据系统总内存自动调整。 在内存管理的其他关键文件中,如`mm/memory.c`和`mm/page.s`,包含了更深入的内存管理逻辑,比如页表的维护、页面的分配和回收等。而在`kernel/fork.c`和`lib/malloc.c`中,我们可以看到如何处理进程创建时的内存复制以及动态内存分配的实现。 Linux 0.11的内存管理策略充分考虑了早期硬件的限制,通过精心的布局和初始化,确保了系统在有限的内存资源下能高效运行。内存初始化是这一策略的起点,它为后续的内存分配、进程管理和系统运行奠定了基础。

/* * Record.c * * Created on: 2014-5-26 * Author: zdl */ #include "includes.h" char *const Display_Name[]={ "Music List", "1-Beyond.wav", "2-LetItG.wav", "3-WeAreO.wav", "4-FanFan.wav", "5-OldBoy.wav", "6-Sodagr.wav", "7-WangF1.wav", "8-WangF2.wav", "9-Mayday.wav", "10-StevC.wav", }; void Music_Graph() { SysTickDisable(); //---------Draw Title---------- ui8Flush_Flag=FLUSH_ON; GrClearDisplay(&g_sContext); GrFlush(&g_sContext); } void Music_Begin() { DSTATUS i=1; SystemClock=SysCtlClockGet(); //----------------硬件初始化--------------- DAC_Init(); //初始化DAC //-------------------初始化SD卡-------------------- while(i==1)// 使用文件系统初始化SD卡 i=disk_initialize(0); //-------------------初始化Timer------------------- SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); TimerDisable(TIMER1_BASE, TIMER_A); TimerConfigure(TIMER1_BASE, TIMER_CFG_A_PERIODIC_UP); TimerIntRegister(TIMER1_BASE,TIMER_A,Timer1IntHandler); TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); MAP_GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_6); MAP_GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_6,GPIO_PIN_6); SysTickEnable(); } void Music_Main() { static uint8_t preDisplay_Num=255,Display_Num=0; while((ui8ButtonKeyValue&KEY_LEFT_ENTER) == 0 &&(ui8ButtonKeyValue&KEY_RIGHT_EXIT)==0) { Display_Num = GetWheelKey(); _nop(); if(Display_Num != preDisplay_Num) { DrawMenu(Display_Num,Display_Name); preDisplay_Num = Display_Num; } SysCtlDelay(SystemClock/100); } if(Music_Enter==1) { GrClearDisplay(&g_sContext); GrStringDrawCentered(&g_sContext, Display_Name[Display_Num], AUTO_STRING_LENGTH, 63, 20, OPAQUE_TEXT); GrContextFontSet(&g_sContext, &g_sFontFixed6x8); GrStringDraw(&g_sContext,"Time:",4,0,53,1); GrStringNumberCentered(&g_sContext,0,0,35+22,57); GrStringDraw(&g_sContext,"-",1,35+9,53,1); GrStringNumberCentered(&g_sContext,0,0,35+2,57); GrStringDraw(&g_sContext,"/",1,35+34,53,1); GrStringNumberCentered(&g_sContext,0,0,35+48,57); GrStringDraw(&g_sContext,"-",1,35+55,53,1); GrStringNumberCentered(&g_sContext,0,0,35+70,57); GrFlush(&g_sContext); ui8Flush_Flag=FLUSH_OFF; WaveOpen(Display_Name[Display_Num],MONO); ui8Flush_Flag=FLUSH_ON; preDisplay_Num=255; ui8ButtonKeyValue&=~(KEY_LEFT_ENTER+KEY_RIGHT_EXIT); } else { preDisplay_Num=255; rcd_ply_sel = 255; } } void Music_Quit() { MAP_GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5,0); TimerDisable(TIMER1_BASE, TIMER_A); ui8Flush_Flag=FLUSH_ON; }

2023-07-11 上传