0
我目前正在開發一個小內核項目,以瞭解更多關於系統開發的內容。我正面臨着一個奇怪的錯誤:我只是製作和調試了一個簡單的內存分配器(kmalloc()和kfree()函數),並且它工作得很好。當我打印由kmalloc()返回的指針的地址時,除了1指針之外,所有東西都可以工作!當我打印這個指針的地址兩次(用kprintf(「addr =%x(%x)」,i64,i64))我看到「addr = 0000(F018)」。 這是代碼和輸出:內核開發,內存分配器和kprintf()奇怪的輸出
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);
}
對不起,如果這不正確,如果你需要更多的細節,請讓我知道...這個問題並不重要,因爲它似乎指針有正確的地址,但它只是奇怪的,我想要知道爲什麼... 感謝您的閱讀!
您的目標是64位系統嗎?那麼指針的大小是多少?什麼大小是一個'int'(或'u32')?考慮一下,爲什麼標準'printf'有一個特殊的''%p''格式來打印指針('void *')。 –
另外,你的'i2hex'函數在做什麼?最後一個論點的含義是什麼? –
最後,Qemu允許你附加一個調試器。我建議你這樣做,並通過代碼來看看它真的做了什麼。 –