我现在遇到页面错误,这意味着我正在访问无效地址。这很可能是我选择遵循的高半内核设计。但我看不出它在哪里导致页面错误。这是我的 kernel.c++
#include "types.h"
#include "gdt.h"
#include "stdio.h"
#include "serial.h"
#include "mem.h"
#include "idt.h"
#include "timer.h"
#include "isr.h"
#include "kbd.h"
#include "mouse.h"
#include "irq.h"
#include "string.h"
#include "terminal.h"
#include "multiboot.h"
#include "pmm.h"
#include "heap.h"
//Call all class constructor
//for global objects before
//calling the kernel
typedef void (*constructor)();
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" void callConstructors()
{
for(constructor* i = &start_ctors; i != &end_ctors; i++)
(*i)();
}
extern "C" void kernelMain(uint32_t kernel_virtual_end,
uint32_t kernel_physical_end,
uint32_t placeholder,
uint32_t kernel_physical_start, uint32_t kernel_virtual_start,
multiboot_info_t *multiboot_structure,uint32_t magicnumber
)
{
cls();
printf("******KERNEL INFO********\n");
printf("KERNEL START VIRTUAL 0x%x\n" , kernel_virtual_start);
printf("KERNEL START PHYSICAL 0x%x\n" , kernel_physical_start);
printf("KERNEL END VIRTUAL 0x%x\n" , kernel_virtual_end);
printf("KERNEL END PHYSICAL 0x%x\n" , kernel_physical_end);
printf("MAGIC 0x%x\n" , magicnumber);
printf("*************************");
// printf("********RAM INFO*********\n");
//
//
// printf("Memory Upper : %d \n", multiboot_structure->mem_upper);
// printf("Memory Lower : %d \n", multiboot_structure->mem_lower);
//
// printf("*************************\n");
gdt gt;
IDT idt;
ISR isr;
IRQ irq;
SerialPort sp;
isr.install_isrs();
irq.install_irqs();
Timer timer;
timer.install_timer();
KBD kbd;
kbd.install_kbd_driver();
MOUSE mouse;
mouse.install_mouse_driver();
__asm__ __volatile__ ("sti");
PhyiscalMemoryManager pmm(multiboot_structure);
KHEAP kheap;
char *ptr;
Heap heap((&kheap));
heap.k_addBlock(&kheap, (0x100000+0xC0000000), (0x100000+0xC0000000));
//ptr = (char*)heap.k_malloc(&kheap, 256);
//heap.k_free(&kheap, ptr);
while(1);
err:
while(1);
}
好的,您可以看到我注释掉了最后几行.. k_malloc() 是导致所有混乱的原因。出于某种原因,它的 malloc() 低于 0xC0100000 ,这是我们可以为内核设置的最小大小,因为我们使用的是虚拟地址,并且 1MB 是 Grub 相关的东西。说这是我的 heap.c++ :
#include "heap.h"
int Heap::k_addBlock(KHEAPLCAB *heap, uintptr_t addr, uint32_t size)
{
KHEAPBLOCKLCAB *hb;
KHEAPHDRLCAB *hdr;
hb = (KHEAPBLOCKLCAB*)addr;
hb->size = size;
hb->used = 0;
hb->next = heap->fblock;
heap->fblock = hb;
hdr = (KHEAPHDRLCAB*)&hb[1];
hdr->flagsize = hb->size - (sizeof(KHEAPBLOCKLCAB) + 32);
++heap->bcnt;
hb->lastdsize = 0;
hb->lastdhdr = 0;
return 1;
}
/*
Look behind and forward to see if we can merge back into some chunks.
*/
void Heap::k_free(KHEAPLCAB *heap, void *ptr)
{
KHEAPHDRLCAB *hdr, *phdr, *nhdr;
KHEAPBLOCKLCAB *hb;
uint32_t sz;
uint8_t fg;
hdr = (KHEAPHDRLCAB*)ptr;
hdr[-1].flagsize &= ~0x80000000;
phdr = 0;
/* find the block we are located in */
for (hb = heap->fblock; hb; hb = hb->next)
{
if (((uintptr_t)ptr > (uintptr_t)hb) && ((uintptr_t)ptr < (uintptr_t)hb + hb->size))
{
hdr = (KHEAPHDRLCAB*)((uintptr_t)ptr - sizeof(KHEAPHDRLCAB));
hdr->flagsize &= ~0x80000000;
hb->used -= hdr->flagsize;
if (hdr->prevsize)
{
phdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr - (sizeof(KHEAPHDRLCAB) + hdr->prevsize));
}
else
{
phdr = 0;
}
/* get next header */
nhdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + hdr->flagsize);
if ((uintptr_t)nhdr >= ((uintptr_t)hb + hb->size))
{
nhdr = 0;
}
if (nhdr)
{
if (!(nhdr->flagsize & 0x80000000))
{
/* combine with it */
hdr->flagsize += sizeof(KHEAPHDRLCAB) + nhdr->flagsize;
hb->used -= sizeof(KHEAPHDRLCAB);
/* set next header prevsize */
nhdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + hdr->flagsize);
nhdr->prevsize = hdr->flagsize;
}
}
if (phdr)
{
if (!(phdr->flagsize & 0x80000000))
{
phdr->flagsize += sizeof(KHEAPHDRLCAB) + hdr->flagsize;
hb->used -= sizeof(KHEAPHDRLCAB);
hdr = phdr;
nhdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + hdr->flagsize);
if ((uintptr_t)nhdr < (uintptr_t)hb + sizeof(KHEAPBLOCKLCAB) + hb->size)
{
nhdr->prevsize = hdr->flagsize;
}
}
}
/* optimization */
if (hdr->flagsize > hb->lastdsize)
{
hb->lastdsize = hdr->flagsize;
hb->lastdhdr = hdr;
}
return;
}
}
printf("uhoh ptr:%p\n", ptr);
for (hb = heap->fblock; hb; hb = hb->next) {
printf("lcab free looking at block:%p next:%p ptr:%p end:%p\n", hb, hb->next, ptr, (uintptr_t)hb + hb->size);
if (((uintptr_t)ptr > (uintptr_t)hb)) {
printf("above\n");
if (((uintptr_t)ptr < ((uintptr_t)hb + hb->size))) {
printf("found\n");
}
}
}
for (;;);
/* uhoh.. this should not happen.. */
return;
}
/*
This will allocate a chunk of memory by the specified size, and if
no memory chunk can be found it will return zero.
*/
void* Heap::k_malloc(KHEAPLCAB *heap, uint32_t size)
{
KHEAPBLOCKLCAB *hb;
KHEAPHDRLCAB *hdr, *_hdr, *phdr;
uint32_t sz;
uint8_t fg;
uint32_t checks;
uint32_t bc;
checks = 0;
bc =0;
for (hb = heap->fblock; hb; hb = hb->next) {
if ((hb->size - hb->used) >= (size + sizeof(KHEAPHDRLCAB))) {
++bc;
hdr = (KHEAPHDRLCAB*)&hb[1];
phdr = 0;
while ((uintptr_t)hdr < ((uintptr_t)hb + hb->size)) {
++checks;
fg = hdr->flagsize >> 31;
sz = hdr->flagsize & 0x7fffffff;
if (!fg)
{
if (sz >= size)
{
if (sz > (size + sizeof(KHEAPHDRLCAB) + 16))
{
_hdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + size);
_hdr->flagsize = sz - (size + sizeof(KHEAPHDRLCAB));
_hdr->prevsize = size;
hdr->flagsize = 0x80000000 | size;
hb->used += sizeof(KHEAPHDRLCAB);
}
else
{
hdr->flagsize |= 0x80000000;
}
hb->used += size;
return &hdr[1];
}
}
phdr = hdr;
hdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + sz);
}
}
}
return 0;
}
Heap::Heap(KHEAPLCAB *heap)
{
heap->fblock = 0;
heap->bcnt = 0;
}
Heap::~Heap()
{
}
我认为问题出在 malloc() 上,因为当我将其注释掉时,一切正常。我正在访问该函数中的一些无效地址:
void* Heap::k_malloc(KHEAPLCAB *heap, uint32_t size)
{
KHEAPBLOCKLCAB *hb;
KHEAPHDRLCAB *hdr, *_hdr, *phdr;
uint32_t sz;
uint8_t fg;
uint32_t checks;
uint32_t bc;
checks = 0;
bc =0;
for (hb = heap->fblock; hb; hb = hb->next) {
if ((hb->size - hb->used) >= (size + sizeof(KHEAPHDRLCAB))) {
++bc;
hdr = (KHEAPHDRLCAB*)&hb[1];
phdr = 0;
while ((uintptr_t)hdr < ((uintptr_t)hb + hb->size)) {
++checks;
fg = hdr->flagsize >> 31;
sz = hdr->flagsize & 0x7fffffff;
if (!fg)
{
if (sz >= size)
{
if (sz > (size + sizeof(KHEAPHDRLCAB) + 16))
{
_hdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + size);
_hdr->flagsize = sz - (size + sizeof(KHEAPHDRLCAB));
_hdr->prevsize = size;
hdr->flagsize = 0x80000000 | size;
hb->used += sizeof(KHEAPHDRLCAB);
}
else
{
hdr->flagsize |= 0x80000000;
}
hb->used += size;
return &hdr[1];
}
}
phdr = hdr;
hdr = (KHEAPHDRLCAB*)((uintptr_t)&hdr[1] + sz);
}
}
}
return 0;
}
. 帮助将不胜感激。这是我在 Github 中的完整源代码:https ://github.com/amanuel2/OS_MIRROR