c - 启用分页后出现页面错误?操作系统开发
问题描述
我正在尝试制作自己的操作系统。我得到了中断工作,一些键盘和鼠标驱动程序,基本的视频和打印功能。现在我想进入内存管理和任务,我意识到的第一件事是我需要尚未正确设置的分页。
我遵循了一些指南和教程,最主要的是在 osdev wiki ( https://wiki.osdev.org/Setting_Up_Paging ) 中设置分页教程。我“编写”(基本上是复制和粘贴)以下代码以初始化分页。
void initPaging()
{
unsigned int i;
for(i = 0; i < 1024; i++)
{
// This sets the following flags to the pages:
// Supervisor: Only kernel-mode can access them
// Write Enabled: It can be both read from and written to
// Not Present: The page table is not present
page_directory[i] = 0x00000002;
}
//we will fill all 1024 entries in the table, mapping 4 megabytes
for(i = 0; i < 1024; i++)
{
// As the address is page aligned, it will always leave 12 bits zeroed.
// Those bits are used by the attributes ;)
first_page_table[i] = (i * 0x1000) | 3; // attributes: supervisor level, read/write, present.
}
page_directory[0] = ((unsigned int)first_page_table) | 3;
enablePaging(page_directory);
}
该enablePaging
函数将页面目录加载到cr3,然后通过设置cr0中的PG位来启用分页。
问题是在调用它之后,如果我调用其他任何东西,比如 printk,它会导致页面错误。我认为那是因为我没有识别内核页面或其他东西。在我的页面错误处理程序中,我将错误代码移动到 eax 并检查 qemu 监视器中的寄存器。错误代码是 0x00000020 这是
0 1 0 - 监督进程试图写入一个不存在的页面条目
TL;博士
启用分页后我不能调用其他任何东西,我需要映射我的内核吗?我怎么做?还有什么问题?
这是我在 github 上的代码: https ://github.com/Danyy427/PagingOsdev
我的异常处理程序:
void isr14_handler(interrupt_frame_t *frame)
{
//panic("Page Fault");
unsigned int err = frame->err_code;
//asm(".intel_syntax noprefix");
asm("mov %0, %%eax "::"r"(err));
while(1);
}
我注释掉了恐慌,因为它会导致双重故障,从而导致三重故障。我将错误代码放入 eax 并且代码挂起,这是预期的。
解决方案
我终于明白了。我的内核有以下代码:
initPaging();
printk("Hello %d", 15) ;
启用分页后,我试图打印一些东西并意识到 printk 引发了页面错误错误。我去 printk 代码并意识到我正在访问 0xFD000000,这是 QEMU 的帧缓冲区地址。但我没有映射它,所以程序试图访问一个未映射的位置。我在我的 initPaging 函数中编写了以下代码,将 0xFD000000 映射到 0x400000:
int from = 0x00000000, size = 0x400000, zz = 0;
for(; size>0; from += 4096, size -= 4096, zz++){
first_page_table[zz] = from | 1; // mark page present.
}
from = 0xFD000000;
size = 0x400000;
zz = 0;
for(; size>0; from += 4096, size -= 4096, zz++){
second_page_table[zz] = from | 1; // mark page present.
}
vbemode.framebuffer = 0x400000;
page_directory[0] = ((unsigned int)first_page_table) | 3;
page_directory[1] = ((unsigned int)second_page_table) | 3;
enablePaging(page_directory);
该代码映射了从物理地址 0xFD000000 的 0x400000 到 0x800000(希望如此)的 4 MB 内存,从而可以访问视频内存。
随时指出我在代码中的错误。
推荐阅读
- python - 如何使用python从excel文件中删除标题
- bash - 通过 Bash shell WSL1 安装 Yarn
- python - DjangoCMS - 具有共享页面的多个站点
- macos - SCP 无法识别来自 .ssh/config 的配置
- owasp - 无法对在 zap 中创建的警报应用警报过滤器
- c++ - 我还能将 wxIndustrialControls 用于 wxWidgets 吗?LNK2019 错误
- php - woocommerce_login_redirect 到购物车(如果不为空)
- python - XOR 神经网络 python
- node.js - 我应该为 Google Cloud Tasks 的每个任务中的每个任务创建新的 PubSub 实例吗?
- c# - 在 Raspberry Pi 4 上部署 OpenCV - 'Emgu.CV.CvInvoke' 的类型初始化程序引发异常