>

현재 시스템 개발에 대해 배우기 위해 작은 커널 프로젝트를 진행하고 있습니다. 나는 이상한 버그에 직면하고있다 : 나는 약간의 간단한 메모리 할당 자 (kmalloc () 및 kfree () 함수 만)를 만들고 디버깅했으며 완벽하게 작동한다. kmalloc ()에 의해 반환 된 포인터의 주소를 인쇄하면 1 포인터를 제외한 모든 것이 작동합니다! kprintf ( "addr = % x (% x)", i64, i64)를 사용하여이 포인터의 주소를 두 번 인쇄하면 "addr = 0000 (F018)"이 표시됩니다. 이것은 코드와 출력입니다 :

QEMU에서 출력

CKernel.c :

#include "system.h"
#include "multiboot.h"
#include "util/util.h"
#include "cpu/cpu.h"
#include "video/video.h"
#include "memory/mem.h"
void kmain(multiboot_info_t* mbt)
{
    //Current status : 32 bits, protected mode
    //init
    vga_setup();
    gdt_install();
    idt_install(); //TODO : ISRs ! (actually the only interrupt handler is a method that just print "INTERRUPT" and iret)
    cpu_detect(); //TODO : Special handle INVALID_OPCODE
    //TODO : Install PAGING //Need basic DYNAMIC ALLOCATION
    //TODO : Install KHEAP
    u8* i8 = kmalloc(1, 0);
    *i8 = 244;
    kprintf("i8 = %d, addr = %X", *i8, i8);
    u32* i32 = kmalloc(sizeof(u32), 0);
    *i32 = 12;
    kprintf("i32 = %d, addr = %X", *i32, i32);
    kfree(i8);
    u64* i64 = kmalloc(sizeof(u64), 0);
    *i64 = 29999344;
    kprintf("i64 = %d, addr = %x (%X) (%x)", *i64, i64, i64, i64);
    kprintf("%d %x %X", i64, i64, i64);
    //Install ACPI
    //Install PIC
    //Install LAPIC / IOAPIC
    //Install FPU
    /*asm("   movb $0xFF, %al \n \
              outb %al, $0xA1 \n \
              outb %al, $0x21 \n");*/ //PIC DISABLING (DEBUG)
    //asm("sti"); //INTERRUPT ENABLING (DEBUG)
    //asm("int $0x0"); //INT CALL (DEBUG)
    //print done message, to see that everything went well
    kprint("[MAIN] DONE !", 1);
    //kprintf("Lower memory : %dk (0x%x)   Upper memory : %dk (0x%X)", mbt->mem_lower, mbt->mem_lower, mbt->mem_upper, mbt->mem_upper);
    //kter_install();
    //loop infinetely
    while(1) asm("hlt");
}

kmalloc.c :

#include "../system.h"
#include "util/util.h"
typedef struct
{
    u32 size;
    u8 status;
} __attribute__ ((packed)) block_header_t;
#define KHEAP_BASE_START 0xF000
#define KHEAP_BASE_END 0xFFFF
u8 base_heap_initialized = 0;
static void merge_free_blocks();
//Possible improvements : SECURITY : ADD a MAGIC number in the header, so that free() verify that it's a valid block (and malloc too)
void* kmalloc(u32 size, u8 align)
{
    u32 i;
    if(align == 0) align = size;
    //No need to merge as kfree() did it for us, right ?
    //merge_free_blocks();
    if(!base_heap_initialized)
    {
        block_header_t* base_block = (block_header_t*) KHEAP_BASE_START;
        base_block->size = KHEAP_BASE_END - (((u32) base_block) + sizeof(block_header_t));
        base_block->status = 0;
        base_heap_initialized = 1;
    }
    i = KHEAP_BASE_START;
    while(i < KHEAP_BASE_END)
    {
        block_header_t* currentBlock = (block_header_t*) i;
        //kprintf("Looking block at %X... (addr = %X) (size = %d) (status = %s)", i, i+sizeof(block_header_t), currentBlock->size, (currentBlock->status ? "RESERVED" : "FREE"));
        //Check if the current block is free and large enough
        if(!currentBlock->status && currentBlock->size >= size)
        {
            //Apply alignment contraints
            int am = 0;
            while((((u32)currentBlock)+sizeof(block_header_t)+am) % align != 0)
            {
                //kprint("Alignment : 1B used.", 0);
                am++;
                size++;
            }
            //Recheck size after alignment contraints
            if(currentBlock->size >= size)
            {
                int oldSize = currentBlock->size;
                if(oldSize - size > 5)
                {
                    currentBlock->size = size;
                    //Split the block if it is big
                    block_header_t* newblock = (block_header_t*) (i+sizeof(block_header_t)+currentBlock->size);
                    newblock->size = oldSize-size-5;
                    newblock->status = 0;
                    //kprintf("Setting up new block at %X (size = %d) (cbS = %d)", newblock, newblock->size, currentBlock->size);
                }
                //Mark the block as reserved
                currentBlock->status = 1;
                //Return the block
                //kprintf("Returning addr %X", ((u32) (((u32)currentBlock)+sizeof(block_header_t)+am)));
                return ((void*) ((u32)currentBlock)+sizeof(block_header_t)+am);
            }
        }
        //The current block did not match, skipping to next block
        i += (currentBlock->size+sizeof(block_header_t));
    }
    //Heap is full : returning null
    kprint("[GRAVE] [ERROR] The kernel HEAP is FULL ! Returned pointer to NULL !", 2);
    return ((void*) 0);
}
void kfree(void* pointer)
{
    block_header_t* blockHeader = (block_header_t*) (pointer - sizeof(block_header_t));
    blockHeader->status = 0;
    merge_free_blocks();
}
static void merge_free_blocks()
{
    block_header_t* currBlock;
    u32 i = KHEAP_BASE_START;
    while(i < KHEAP_BASE_END)
    {
        currBlock = (block_header_t*) i;
        if(!currBlock->status)
        {
            //Joining free regions
            block_header_t* nextBlock;
            while(!(nextBlock = (block_header_t*) i+sizeof(block_header_t)+currBlock->size)->status)
            {
                currBlock->size+= (sizeof(block_header_t)+nextBlock->size);
                i+=(sizeof(block_header_t)+nextBlock->size);
            }
            i += (sizeof(block_header_t)+((u32)currBlock));
        }
        else
            i+= (sizeof(block_header_t)+((u32)currBlock));
    }
}

kprintf () 함수 :

static void vkprintf(const char* args, va_list ap)
{
    char buffer[32];
    vga_text_puts("[KERNEL] ", 0b00001111);
    while(*args)
    {
        if(*args == '%')
        {
            switch(*(++args))
            {
                case 'u':
                    utoa(va_arg(ap, u32), buffer);
                    vga_text_puts(buffer, 0b00000111);
                    break;
                case 'i': case 'd':
                    itoa(va_arg(ap, int32_t), buffer);
                    vga_text_puts(buffer, 0b00000111);
                    break;
                case 'X': /// TODO: make it standardized
                    i2hex(va_arg(ap, u32), buffer, 8);
                    vga_text_puts(buffer, 0b00000111);
                    break;
                case 'x':
                    i2hex(va_arg(ap, u32), buffer, 4);
                    vga_text_puts(buffer, 0b00000111);
                    break;
                case 'y':
                    i2hex(va_arg(ap, u32), buffer, 2);
                    vga_text_puts(buffer, 0b00000111);
                    break;
                case 's':
                    {
                        char* temp = va_arg(ap, char*);
                        vga_text_puts(temp, 0b00000111);
                        break;
                    }
                case 'c':
                    vga_text_putc((int8_t)va_arg(ap, int32_t), 0b00000111);
                    break;
                default:
                    vga_text_putc(*args, 0b00000111);
                    break;
            }
        }
        else
        {
            vga_text_putc(*args, 0b00000111);
        }
        args++;
    }
    vga_text_putc('\n', 0b00000111);
}
void kprintf(const char* args, ...)
{
    va_list ap;
    va_start(ap, args);
    vkprintf(args, ap);
    va_end(ap);
}

이것이 정확하지 않다면 죄송합니다. 자세한 정보가 필요하면 알려주십시오 ...이 문제는 포인터가 올바른 주소를 가지고있는 것처럼 보이지만 실제로는 중요하지 않습니다. 왜 그런지 알고 싶었습니다 ... 읽어 주셔서 감사합니다!

  • 이전 Service Fabric에서 신뢰할 수있는 액터에 대한 엔드 포인트 정의 (온 프레미스 설정)
  • 다음 android - GPS 재생률