You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何磁盘读取函数会引发页错误?FAT BPB读取故障排查

磁盘读取函数引发页错误的原因分析

读取FAT BPB的函数触发页错误,代码如下:

fat_bpb* fat_read_bpb(){
    fat_bpb* bpb = kmalloc(sizeof(fat_bpb));
    ide_read_sectors(DRIVE, 1, 6, (uint32)bpb);
    return bpb;
}

单步调试发现错误出在ide_read_sectors(DRIVE, 1, 6, (uint32)bpb);这一行,同时GCC给出警告:

initialization of ‘fat_bpb *’ from ‘uint32’ {aka ‘unsigned int’} makes pointer from integer without a cast [-Wint-conversion]

当前使用的kmalloc实现如下:

extern uint32 end;
uint32 placement_address = (uint32)&end;

uint32 kmalloc_int(uint32 sz, int align, uint32 *phys)
{
    // This will eventually call malloc() on the kernel heap.
    // For now, though, we just assign memory at placement_address
    // and increment it by sz. Even when we've coded our kernel
    // heap, this will be useful for use before the heap is initialised.
    if (align == 1 && (placement_address & 0xFFFFF000) )
    {
        // Align the placement address;
        placement_address &= 0xFFFFF000;
        placement_address += 0x1000;
    }
    if (phys)
    {
        *phys = placement_address;
    }
    uint32 tmp = placement_address;
    placement_address += sz;
    return tmp;
}

uint32 kmalloc(uint32 sz)
{
    return kmalloc_int(sz, 0, 0);
}

核心原因:物理地址与虚拟地址混用

  1. kmalloc返回的是物理地址
    当前的kmalloc实现基于placement_address分配内存,而placement_address初始化为(uint32)&end——这里的&end是内核加载到物理内存中的结束地址,所以kmalloc返回的是物理内存地址,而非内核运行时使用的虚拟地址。

  2. 指针误用物理地址导致未映射访问
    在启用分页的系统中,内核代码使用的是虚拟地址空间,物理地址和虚拟地址属于完全不同的地址空间。你将kmalloc返回的物理地址直接赋值给fat_bpb*指针,相当于把物理地址当成虚拟地址去使用:

    • 当ide_read_sectors尝试向该地址写入数据时,CPU会将其视为虚拟地址去查询页表,但这个物理地址对应的虚拟地址并未在页表中完成映射,直接触发页错误。
    • GCC的警告已经明确提示了类型不匹配的问题,本质就是地址空间的错误混用。
  3. IDE函数的参数要求加剧问题
    如果ide_read_sectors的第四个参数需要的是虚拟地址,那么传入物理地址必然导致访问无效地址;如果它需要的是物理地址,那后续通过bpb指针访问内存时(同样把物理地址当虚拟地址用)也会触发页错误。而你单步调试发现错误出在ide_read_sectors调用行,说明函数内部在访问该地址时是按虚拟地址处理的。

解决方向

  • 修改kmalloc实现,使其返回虚拟地址,确保分配的内存区域已经在页表中完成映射。
  • 若IDE函数需要物理地址,可使用kmalloc_int的phys参数同时获取物理地址和虚拟地址:用虚拟地址作为指针使用,物理地址传给IDE函数。
  • 修复类型转换问题,避免直接将uint32类型的地址赋值给指针,明确区分物理地址与虚拟地址的使用场景。

内容的提问来源于stack exchange,提问作者xingharvey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:05:35