简介
上一节实现了对内存信息的解析,操作系统的一个重要功能就是提供内存管理,为应用程序提供动态内存分配。一个好的内存管理算法不会使系统内存资源耗尽、内存碎片较少。
目标
实现简易的内存分配、回收管理算法。
1.新建memman.h
//内存管理模块
#define MEMMAN_FREES 4096
typedef struct _FREEINFO {
unsigned int *addr, size;
}FREEINFO;
//该结构体空间大小大致为32K
typedef struct _MEMMAN {
//frees 表示空闲内存块的数量
//lostsize 表示丢弃的内存大小
//losts 表示丢弃的内存次数
int frees, maxfrees, lostsize, losts;
struct _FREEINFO free[MEMMAN_FREES];
}MEMMAN;
void memman_init(MEMMAN *man);
unsigned int memman_total(MEMMAN *man);
unsigned int* memman_alloc(MEMMAN *man,unsigned int size);
int memman_free(MEMMAN *man,unsigned int *addr,unsigned int size);
2.新建memman.c
#include"memman.h"
void memman_init(MEMMAN *man){
man->frees = 0;
man->maxfrees = 0;
man->lostsize = 0;
man->losts = 0;
}
unsigned int memman_total(MEMMAN *man){
unsigned int t = 0;
for (int i = 0; i < man->frees; i++) {
t += man->free[i].size;
}
return t;
}
unsigned int* memman_alloc(MEMMAN *man,unsigned int size) {
unsigned int *a;
for (int i = 0; i < man->frees; i++) {
if (man->free[i].size >= size) {
a = man->free[i].addr;
man->free[i].size -= size;
man->free[i].addr = (unsigned int *)(((char *)(man->free[i].addr))+size);
if (man->free[i].size == 0) {//在索引i 后的内存记录块往前搬移
for(int j=i+1;j<man->frees;j++){
man->free[j-1] = man->free[j];
}
man->frees--;
}
return a;
}
}
return (unsigned int*)0;
}
int memman_free(MEMMAN *man,unsigned int *addr,unsigned int size){
unsigned int *offAddr = (unsigned int*)((char *)addr+size);
for(int i=0;i<man->frees;i++){
if((char *)(man->free[i].addr)+man->free[i].size == (char *)addr){//作为高地址合并
man->free[i].size += size;
return 1;
}
else if(man->free[i].addr == offAddr){//作为低地址合并
man->free[i].addr = addr;
man->free[i].size += size;
return 1;
}
}
//作为新增块
man->free[man->frees].addr = addr;
man->free[man->frees].size = size;
man->frees++;
return 1;
}
3.os.c init_main函数中添加如下
_memman = (MEMMAN *)0x010000;
memman_init(_memman);
_memman->frees = 1;
_memman->free[0].addr = (unsigned int *)(0x010000+0x8000);
_memman->free[0].size = (0x01fef000-0x8000);
int memToal = memman_total(_memman);
for(int j=0;j<4;j++){
temp = char2HexStr(((char *)&memToal)[3-j]);
_tempArr[2+2*j] = ((char *)&temp)[0];
_tempArr[3+2*j] = ((char *)&temp)[1];
}
_charCount += 10;
showString(_tempArr,10,true);
4.编译memman.c
clang -c -m32 memman.c -o memman.o
5.编译os.c
clang -c -m32 os.c -o os.o
6.链接memman.o 和 os.o
ld -m elf_i386 -r os.o memman.o -o os-mem.o
7.反汇编os-mem.o
./objconv -fnasm os-mem.o -o os.s
并去除global、extern、SECTION 等申明信息
8.加载并运行floppy.img,虚拟机使用的内存为512M。依次按下回车键到os.c 中低4字节内存地址等于0x010000效果如下:
以上做了一个大致的内存分配显示,os.c 中解析的内存地址和长度都是固定的!