홈>
현재 시스템 개발에 대해 배우기 위해 작은 커널 프로젝트를 진행하고 있습니다. 나는 이상한 버그에 직면하고있다 : 나는 약간의 간단한 메모리 할당 자 (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);
}
이것이 정확하지 않다면 죄송합니다. 자세한 정보가 필요하면 알려주십시오 ...이 문제는 포인터가 올바른 주소를 가지고있는 것처럼 보이지만 실제로는 중요하지 않습니다. 왜 그런지 알고 싶었습니다 ... 읽어 주셔서 감사합니다!
- 답변 # 1
관련 자료
- c++ - 이 메모리 할당자는 블록의 주소를 어떻게 얻습니까?
- c의 커스텀 메모리 할당 자
- python - 커널 오류 또는 메모리 오류를 해결하는 방법?
- python 3.x - 커널이 사망 한 것으로 보입니다 자동으로 다시 시작됩니다 메모리 문제?
- c - 커널 메모리 누출 감지기
- c++ - cuda 커널 런타임 감소 - 커널에서 행렬의 동적 메모리 할당
- architecture - 게임 엔진 메모리 할당 자
- 커널 메모리가 수정되었는지 Windows 커널은 어떻게 알 수 있습니까?
- 사용 된 프로세스의 더 높은 가상 메모리 주소 (커널 매핑)는 무엇입니까?
- Memory layout and kernel space - 메모리 레이아웃 및 커널 공간 - 사용자 공간
관련 질문
- c : 문자열을 동적으로 할당하는 것과 관련하여 약간의 질문이 있습니다. 어떻게 해결할 수 있습니까?
- c : 책 제목, 저자 및 주제를 읽고 4를 선택하고 책 제목을 입력할 때 컴파일러의 출력 화면에 인쇄하는 방법을 아는 사람이 있습니까?
- arrays : 단일 배열에 대한 sscanf 다중 형식 지정자
- arrays : C -라이브러리 함수 없이 문자열 복사
- 주소에서 C의 포인터 생성
- 매트릭스 메모리 할당은 동적 배열이 C에서 초기화되는 것을 허용하지 않습니까?
- arrays : 포인터로서의 다차원 배열 -하위 배열의 주소는 어디에 저장됩니까?
- arrays : 행렬 행렬식 계산의 오류는 무엇입니까?
- arrays : 경고: int*에서 int로의 할당은 캐스트 없이 정수에서 포인터를 만듭니다.
- c : 포인터 산술 등가
좋아요, 문제가 해결되었습니다! 그것은 u64와 모든 itoa () i2hex () 함수의 버그 일뿐입니다. 최대 32 비트를 허용했기 때문에 버퍼에 여전히 32 비트가 있었고 다른 인수 (주소) 대신 printf로 읽었습니다. ! 답변 주셔서 감사합니다 일부 프로그래머 친구, 당신은 해결책으로 나를 이끌었습니다!