30天自制操作系统开发笔记——内存管理

这本书开发的操作系统,用到了下面的内存分布图:

0x00000000 - 0x000fffff : 启动中多次使用,存放VRAM等内容(1MB)
0x00100000 - 0x00267fff : 用于保存软盘的内容。(1440KB)
0x00268000 - 0x0026f7ff : 空(30KB)
0x0026f800 - 0x0026ffff : IDT(2KB)
0x00270000 - 0x0027ffff : GDT(64KB)
0x00280000 - 0x002fffff : bootpack.hrb(512KB)
0x00300000 - 0x003fffff : 栈及其他(1MB)
0x00400000 - :空

根据qemu的设定,整个程序占用的最大内存为32MB

内存管理的内容主要包括内存分配,内存回收

内存分配:

对于这32MB的内存,以4KB为最小单位,用链式的方法去管理,并且遵循每一个未分配的内存块按照地址从小到大排列,每次分配内存时,找到一个不小于要求的大小的内存块分配出去,当一块内存完全分配之后,要把其从链表中删除。

View Code
#define EFLAGS_AC_BIT 0x00040000
#define CR0_CACHE_DISABLE    0x60000000
#define MEMMAN_FREES     4090
#define MEMMAN_ADDR     0x003c0000

struct FREEINFO
{
    unsigned addr,size;
};

struct MEMMAN
{
    int frees,maxfrees,lostsize,losts;
    struct FREEINFO free[MEMMAN_FREES];
};/*要用到的结构体及宏定义*/

void memman_init(struct MEMMAN *man)
{
    man->frees=0;        /*可用信息数目*/
    man->maxfrees=0;    /*观察可用情况,frees的最大值*/
    man->lostsize=0;    /*释放失败的内存的大小总和*/    
    man->losts=0;        /*释放失败次数*/
}/*初始化*/

unsigned int memman_alloc(struct MEMMAN *man,unsigned int size)
{
    unsigned int i,a;
    for(i=0;i<man->frees;i++)
    {
        if(man->free[i].size>=size)
        {
            a=man->free[i].addr;
            man->free[i].addr+=size;
            man->free[i].size-=size;
            if(man->free[i].size==0)
            {
                man->frees--;
                for(;i<man->frees;i++)
                {
                    man->free[i]=man->free[i+1];/*这一段内存被完全占用,删掉记录*/
                }
            }
            return a;
        }
    }
    return 0;
}/*内存分配,返回得到内存的起始地址*/

内存回收:

回收时要注意回收的内存和可以连接到一起的内存连接起来

View Code
int memman_free(struct MEMMAN *man,unsigned int addr,unsigned int size)
{
    int i,j;
    /*先决定放在什么位置上*/
    for(i=0;i<man->frees;i++)
    {
        if(man->free[i].addr>addr)
            break;
    }
    if(i>0)/*前面有可用内存*/
    {
        if(man->free[i-1].addr+man->free[i-1].size==addr)/*可以和前面的连到一起*/
        {
            man->free[i-1].size+=size;
            if(i<man->frees)/*后面有可用内存*/
            {
                if(addr+size==man->free[i].addr)
                {
                    man->free[i-1].size+=man->free[i].size;
                    man->frees--;
                    for(;i<man->frees;i++)
                        man->free[i]=man->free[i+1];
                }
            }
            return 0;
        }
    }
    if(i<man->frees)/*前面没有可用内存,或者不能跟前面内存连到一起*/
    {
        if(addr+size==man->free[i].addr)/*可以和后面连到一起*/
        {
            man->free[i].addr=addr;
            man->free[i].size+=size;
            return 0;
        }
    }
    if(man->frees<MEMMAN_FREES)
    {
        for(j=man->frees;j>i;j--)
        {
            man->free[j]=man->free[j-1];
        }
        man->frees++;
        if(man->maxfrees<man->frees)
        {
            man->maxfrees=man->frees;
        }
        man->free[i].addr=addr;
        man->free[i].size=size;
        return 0;
    }
    /*不能往后移动的*/
    man->losts++;
    man->lostsize+=size;
    return -1;/*失败*/
}
原文地址:https://www.cnblogs.com/caozhenhai/p/2935675.html