我正在尝试为我的C内核编写一个基本的页面管理器。代码如下:
#define NUM_PAGES 1024
#define PAGE_SIZE 4096
#define NULL 0
#define IMPORTANT_SEGMENT 0xC0900000
struct page {
void * addr;
int in_use;
};
struct page CORE_FILE[NUM_PAGES];
void mem_init() {
for (int i = 0; i < NUM_PAGES; i++) {
CORE_FILE[i].addr = (void*)IMPORTANT_SEGMENT+PAGE_SIZE*i;
CORE_FILE[i].in_use = 0;
}
}
void * allocate() {
for (int i = 0; i < NUM_PAGES; i++) {
if (!CORE_FILE[i].in_use) {
CORE_FILE[i].in_use = 1;
return CORE_FILE[i].addr;
}
}
return NULL;
}
int deallocate(void* p) {
for (int i = 0; i < NUM_PAGES; i++) {
if (CORE_FILE[i].addr == p && CORE_FILE[i].in_use) {
CORE_FILE[i].in_use = 0;
return 0;
}
}
return -1;
}
CORE_FILE是一个结构数组,其中仅包含一个用于告知页面是否正在使用的字段和一个地址(即使用从IMPORTANT_SEGMENT = 0xC0900000增长的连续地址)。
当我打电话给allocate()
时,它返回给我正确的void*
,例如我将其强制转换为char,但是当我写地址时,它什么也没做。
我检查了GDB指向的地址,它是正确的地址。 但是当我检查其内容时,它们尚未更新(仍然为0)。
void kmain(void) {
mem_init();
int * addr = (int*)allocate();
*addr = 5;
}
我给qemu 4 GB的RAM执行:
qemu-system-i386 -m 4G -kernel kernel -gdb tcp::5022
也许我正在写一个不存在的内存,或者也许之后我会覆盖地址内容。我不知道。
任何想法都会受到赞赏。
谢谢。
[edit]这是使用以下程序的引导加载程序即时通讯
:bits 32
section .text
;multiboot spec
align 4
dd 0x1BADB002 ;magic
dd 0x00 ;flags
dd - (0x1BADB002 + 0x00) ;checksum. m+f+c should be zero
global start
global keyboard_handler
global read_port
global write_port
global load_idt
extern kmain ;this is defined in the c file
extern keyboard_handler_main
read_port:
mov edx, [esp + 4]
;al is the lower 8 bits of eax
in al, dx ;dx is the lower 16 bits of edx
ret
write_port:
mov edx, [esp + 4]
mov al, [esp + 4 + 4]
out dx, al
ret
load_idt:
mov edx, [esp + 4]
lidt [edx]
sti ;turn on interrupts
ret
keyboard_handler:
call keyboard_handler_main
iretd
start:
cli ;block interrupts
mov esp, stack_space
call kmain
hlt ;halt the CPU
section .bss
resb 8192; 8KB for stack
stack_space:
我的link.ld
OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
SECTIONS
{
. = 0x100000;
.text : { *(.text) }
. = 0x200000;
.data : { *(.data) }
. = 0x300000;
.bss : { *(.bss) }
}
Edit2:我用它编译
nasm -f elf32 kernel.asm -o kasm.o
gcc -g -fno-stack-protector -fno-builtin -m32 -c memory.c -o memory.o
gcc -g -fno-stack-protector -fno-builtin -m32 -c kernel.c -o kc.o
ld -m elf_i386 -T link.ld -o kernel kasm.o memory.o kc.o
答案 0 :(得分:1)
问题在于保护模式和实模式,当计算机启动时,它以16位实模式启动,因此您可以寻址1 MB的数据。上面的所有内容都不适合读/写。如果我将IMPORTANT_SEGMENT更改为0x300000,它将起作用。
现在我必须创建并加载我的gdt,启用a20线,启用保护模式,设置寄存器并跳转到我的代码。