zl程序教程

您现在的位置是:首页 >  其他

当前栏目

0x08_自制操作系统My-OS实现内存管理

2023-04-18 15:39:21 时间

内存管理就是内存管理,我不会像书一样解释。我直接教你怎么实现

还是把class05改class06或者复制一份

内存管理第一件事情就是要划出一篇区域,规定这个地方是内存区域

double *ptd = (double * ) memman_alloc (memman,30 * sizeof(double));和直接double ptd[30]有什么不同

double *ptd = (double * ) memman_alloc (memman,30 * sizeof(double)); 是使用内存管理函数memman_alloc分配了30个double类型数据的连续内存块,并将该内存块的起始地址赋值给指针变量ptd,即ptd指向了这段连续的内存空间。这种方式分配的内存空间是在程序运行时动态分配的,因此可以灵活控制内存使用,但需要手动管理内存的分配和释放。

double ptd[30] 是在栈上直接分配了一个长度为30的double数组,编译器会在编译时就为该数组分配内存空间,因此在程序运行时可以直接使用,不需要手动管理内存的分配和释放。这种方式分配的内存空间是静态分配的,因此在编译时需要确定数组长度,不能动态调整内存使用。

我们造的是操作系统,你开应用程序的时候是动态给他内存,关闭程序的时候是动态释放内存,内存管理是必要的。

head.h

int load_cr0(void);
void store_cr0(int cr0);

放这里

//memory.c
#define MEMMAN_ADDR 0x003c0000
#define EFLAGS_AC_BIT 0x00040000
#define CR0_CACHE_DISABLE 0x60000000

#define MEMMAN_FREES 4090 /* 大约是32KB*/
struct FREEINFO { /* 可用信息 */
    unsigned int addr, size;
};
struct MEMMAN { /* 内存管理 */
    int frees, maxfrees, lostsize, losts;
    struct FREEINFO free[MEMMAN_FREES];
};
void memman_init(struct MEMMAN *man);
unsigned int memman_total(struct MEMMAN *man);
unsigned int memtest(unsigned int start, unsigned int end);
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size);
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size);
void memory();
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size);
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size);

这个也加到head.h,这是memory.c的头文件

naskfun.asm

; naskfunc
; TAB=4

[FORMAT "WCOFF"]                ; 制作目标文件的模式    
[INSTRSET "i486p"]                ; 使用到486为止的指令
[BITS 32]                        ; 3制作32位模式用的机器语言
[FILE "naskfunc.asm"]            ; 文件名
    GLOBAL _io_hlt,_write_mem8,_io_cli,_io_sti,_io_get8,_io_set8,_io_stihlt
    GLOBAL _io_load_eflags,_io_store_eflags,_asm_inthandler21
    GLOBAL _load_gdtr, _load_idtr,_load_cr0,_store_cr0
    GLOBAL _memtest_sub
    EXTERN _inthandler21

[SECTION .text]

_io_hlt:    ; void io_hlt(void);
        HLT
        RET

_io_cli:    ; void io_cli(void);
        CLI
        RET

_io_sti:    ; void io_sti(void);
        STI
        RET

_io_get8:    ; int io_get8(int port);
        MOV        EDX,[ESP+4]        ; port
        MOV        EAX,0
        IN        AL,DX
        RET

_io_set8:    ; void io_set8(int port, int data);
        MOV        EDX,[ESP+4]        ; port
        MOV        AL,[ESP+8]        ; data
        OUT        DX,AL
        RET

_io_stihlt:    ; void io_stihlt(void);
        STI
        HLT
        RET

_write_mem8: ; void write_mem8(int addr, int data);
        MOV ECX,[ESP+4] ; taking content of add
        MOV AL,[ESP+8] ; taking content of data
        MOV [ECX],AL ; *ecx=al
        RET
_io_load_eflags:    ; int io_load_eflags(void);
        PUSHFD        ; PUSH EFLAGS 
        POP        EAX
        RET

_io_store_eflags:    ; void io_store_eflags(int eflags);
        MOV        EAX,[ESP+4]
        PUSH    EAX
        POPFD        ; POP EFLAGS 
        RET
_load_gdtr:        ; void load_gdtr(int limit, int addr);
        MOV        AX,[ESP+4]        ; limit
        MOV        [ESP+6],AX
        LGDT    [ESP+6]
        RET

_load_idtr:        ; void load_idtr(int limit, int addr);
        MOV        AX,[ESP+4]        ; limit
        MOV        [ESP+6],AX
        LIDT    [ESP+6]
        RET
_asm_inthandler21:
        PUSH    ES
        PUSH    DS
        PUSHAD
        MOV        EAX,ESP
        PUSH    EAX
        MOV        AX,SS
        MOV        DS,AX
        MOV        ES,AX
        CALL    _inthandler21
        POP        EAX
        POPAD
        POP        DS
        POP        ES
        IRETD
_memtest_sub: ; unsigned int memtest_sub(unsigned int start, unsigned int end)
        PUSH EDI ; (由于还要使用EBX, ESI, EDI)
        PUSH ESI
        PUSH EBX
        MOV ESI,0xaa55aa55 ; pat0 = 0xaa55aa55;
        MOV EDI,0x55aa55aa ; pat1 = 0x55aa55aa;
        MOV EAX,[ESP+12+4] ; i = start;
mts_loop:
        MOV EBX,EAX
        ADD EBX,0xffc ; p = i + 0xffc;
        MOV EDX,[EBX] ; old = *p;
        MOV [EBX],ESI ; *p = pat0;
        XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
        CMP EDI,[EBX] ; if (*p != pat1) goto fin;
        JNE mts_fin
        XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
        CMP ESI,[EBX] ; if (*p != pat0) goto fin;
        JNE mts_fin
        MOV [EBX],EDX ; *p = old;
        ADD EAX,0x1000 ; i += 0x1000;
        CMP EAX,[ESP+12+8] ; if (i <= end) goto mts_loop;
        JBE mts_loop
        POP EBX
        POP ESI
        POP EDI
        RET
mts_fin:
        MOV [EBX],EDX ; *p = old;
        POP EBX
        POP ESI
        POP EDI
        RET
_load_cr0:        ; int load_cr0(void);
        MOV        EAX,CR0
        RET
_store_cr0:        ; void store_cr0(int cr0);
        MOV        EAX,[ESP+4]
        MOV        CR0,EAX
        RET

加粗的都是新增的

创建新文件memory.c

#include "include/head.h"

#include <stdio.h>

unsigned int memtest(unsigned int start, unsigned int end)
{
    char flg486 = 0;
    unsigned int eflg, cr0, i;
    /* 确认CPU是386还是486以上的 */
    eflg = io_load_eflags();
    eflg |= EFLAGS_AC_BIT; /* AC-bit = 1 */
    io_store_eflags(eflg);
    eflg = io_load_eflags();
    if ((eflg & EFLAGS_AC_BIT) != 0) { /* 如果是386,即使设定AC=1,AC的值还会自动回到0
    */
        flg486 = 1;
    }
    eflg &= ~EFLAGS_AC_BIT; /* AC-bit = 0 */
    io_store_eflags(eflg);
    if (flg486 != 0) {
        cr0 = load_cr0();
        cr0 |= CR0_CACHE_DISABLE; /* 禁止缓存 */
        store_cr0(cr0);
    }
    i = memtest_sub(start, end);
    if (flg486 != 0) {
        cr0 = load_cr0();
        cr0 &= ~CR0_CACHE_DISABLE; /* 允许缓存 */
        store_cr0(cr0);
    }
    return i;

}


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


unsigned int memman_total(struct MEMMAN *man)
/* 报告空余内存大小的合计 */
{
    unsigned int i, t = 0;
    for (i = 0; i < man->frees; i++) {
    t += man->free[i].size;
    }
    return t;
}


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) {
            /* 如果free[i]变成了0,就减掉一条可用信息 */
                man->frees--;
                for (; i < man->frees; i++) {
                    man->free[i] = man->free[i + 1]; /* 代入结构体 */
                }
            }
            return a;
        }
    }
    return 0; /* 没有可用空间 */
}
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size)
/* 释放 */
{
    int i, j;
    /* 为便于归纳内存,将free[]按照addr的顺序排列 */
    /* 所以,先决定应该放在哪里 */
    for (i = 0; i < man->frees; i++) {
    if (man->free[i].addr > addr) {
    break;
    }
    }
    /* free[i - 1].addr < addr < free[i].addr */
    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->free[i]删除 */
    /* free[i]变成0后归纳到前面去 */
    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) {
    /* free[i]之后的,向后移动,腾出一点可用空间 */
    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; /* 失败 */
}
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size)
{
    unsigned int a;
    size = (size + 0xfff) & 0xfffff000;
    a = memman_alloc(man, size);
    return a;
}

int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size)
{
    int i;
    size = (size + 0xfff) & 0xfffff000;
    i = memman_free(man, addr, size);
    return i;
}
void memory(){
        char s[30];
        struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
        unsigned int memtotal;
        struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;


        
        memtotal = memtest(0x00400000, 0xbfffffff);
        memman_init(memman);
        
        memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 0x0009efff */
        memman_free(memman, 0x00400000, memtotal - 0x00400000);
        // double * ptd;
        // ptd = (double * ) memman_alloc (memman,30 * sizeof(double));
        char q[2048];
        sprintf(s, "memory %dKB free : %dKB",
        memtotal / (1024), memman_total(memman) / (1024));
        putfonts8_asc(binfo->vram, binfo->scrnx, 0, binfo->scrny-16,2, s);
}

在Main里面调用memory方法

最后在makefile里面加上obj

运行:

cd class05
..z_toolsmake.exe run

 

我换了底色,这样显得更加成熟

自制操作系统合集
原文地址:https://www.cnblogs.com/Frank-dev-blog/category/2249116.html
项目github地址rick521/My-OS (github.com)给我点颗star