X86 XV6:bootmain-加载内核ELF头

X86 XV6:bootmain-加载内核ELF头,x86,elf,bootloader,osdev,xv6,X86,Elf,Bootloader,Osdev,Xv6,我一直在分析xv6内核中bootmain.c代码: void bootmain(void) { struct elfhdr *elf; struct proghdr *ph, *eph; void (*entry)(void); uchar* pa; elf = (struct elfhdr*)0x10000; // scratch space // Read 1st page off disk readseg((uchar*)elf, 4096, 0);

我一直在分析xv6内核中bootmain.c代码:

void
bootmain(void)
{
  struct elfhdr *elf;
  struct proghdr *ph, *eph;
  void (*entry)(void);
  uchar* pa;

  elf = (struct elfhdr*)0x10000;  // scratch space

  // Read 1st page off disk
  readseg((uchar*)elf, 4096, 0);

  // Is this an ELF executable?
  if(elf->magic != ELF_MAGIC)
    return;  // let bootasm.S handle error

  // Load each program segment (ignores ph flags).
  ph = (struct proghdr*)((uchar*)elf + elf->phoff);
  eph = ph + elf->phnum;
  for(; ph < eph; ph++){
    pa = (uchar*)ph->paddr;
    readseg(pa, ph->filesz, ph->off);
    if(ph->memsz > ph->filesz)
      stosb(pa + ph->filesz, 0, ph->memsz - ph->filesz);
  }

  // Call the entry point from the ELF header.
  // Does not return!
  entry = (void(*)(void))(elf->entry);
  entry();
}

正在尝试将elf头从磁盘复制到elf地址的内存中,但我不明白它为什么要复制4kb,而elf头本身的大小是52字节

在运行readelf-h内核之后,我得到了关于elf头的以下信息:

Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         3

这就意味着(如果我的数学算得好的话)elf头+程序头表占用的字节不超过148个。

您显示的代码是程序的C代码

在至少读取ELF头之前,程序头的数量是未知的。它们只读取整个第一页(4KB),而不是从磁盘读取两次(一次用于ELF头,然后一次用于程序头)。他们假设组合的程序头和ELF头不超过4kib

最好加载ELF头;确定程序头的大小并将其读入内存;然后读入与每个程序头关联的段。如果ELF头和所有其他头以某种方式超过4kib,则此代码将中断

在阅读了代码和一些xv6文档之后,他们似乎简化了内核ELF文件的加载,以便生成的代码能够适应512字节的引导扇区。读取一次数据可能是一个设计决策,但老实说,他们可能并不期望内核本身有大量的头。只需阅读第一个4KB就很方便和简单

感兴趣的可能是第102页的,其中描述了必须进行简化以将引导加载程序代码(和ELF加载程序)放入512字节引导扇区的事实:

本附录中描述的引导加载程序可编译约470字节的机器代码,具体取决于编译C代码时使用的优化为了适应如此小的空间,xv6引导加载程序做出了一个主要的简化假设,即内核已从扇区1开始连续写入引导磁盘。更常见的是,内核存储在普通的文件系统中,它们可能不是连续的,或者通过网络加载。这些复杂性要求引导加载程序能够驱动各种磁盘和网络控制器,并理解各种文件系统和网络协议。换句话说,引导加载程序本身必须是一个小型操作系统。由于如此复杂的引导加载程序肯定无法容纳512字节,因此大多数PC操作系统使用两步引导过程。首先,一个简单的引导加载程序(如本附录中的引导加载程序)从一个已知的磁盘位置加载一个功能齐全的引导加载程序,通常依靠空间较少的BIOS进行磁盘访问,而不是试图驱动磁盘本身。然后,解除512字节限制的完整加载程序可以实现定位、加载和执行所需内核所需的复杂性

我认为可以得出结论,在简化的假设中,有一些是关于引导加载程序中ELF加载程序的设计

Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         3