【问题标题】:Memory management in OS development操作系统开发中的内存管理
【发布时间】:2015-06-25 08:43:23
【问题描述】:

我不确定这个问题是否与主题相关(如果不是,我深表歉意),但我想知道在创建操作系统时如何完成内存管理。我的理解是:

  • 操作系统提供内存管理。
  • 任何编程语言(高于汇编语言,例如 C)都需要已托管的内存(用于堆栈帧和堆分配)。

这听起来很矛盾。如果编写内存管理器的工具首先需要内存管理器,那么如何编写内存管理器?必须在汇编中完成吗?

【问题讨论】:

    标签: c memory-management operating-system


    【解决方案1】:

    C 不需要托管内存。您可能正在考虑malloc 库函数,但这只是一个函数(虽然标准化以供用户 程序使用)。

    一个易于实现的内存分配方案如下:

    char * free_space;
    void * kmalloc(size_t s) {
      char * block = free_space;
      free_space += s;
      return block;
    }
    // free not possible
    

    在初始化期间必须将指针free_space 设置为已知可用内存区域的开头。这可能由引导加载程序通过多重引导信息给出。

    一个更复杂的例子可以在我很久以前写的this code for a kernel中找到。

    一般内存管理分为多个阶段:

    在初始化过程中,像上面这样的简单方案有助于设置更复杂的分配器,就像我写的那样。

    此分配器仅提供固定大小的块(通常为 4Kb,有时也是此大小的倍数)。

    当内存池被填满时,从更高级别的分配器请求这些块。此分配器是您通常通过malloc 调用的分配器。一个突出的例子是 Doug Lea 的 dlmalloc。

    关于栈:编译后的代码做栈指针的递增和递减。但显然它必须在之前设置为一些可用空间。对于内核,在初始化期间,您通常将其设置在您知道是可用内存的某个位置,例如您的二进制文件的一部分。这是在汇编中完成的:

    lea esp, kstack
    ; ...
    call startup_kernel
    ; ...
    [SECTION .bss]
    resb 32768
    kstack:
    

    Startup code in assembly from the aforementioned kernel

    对于稍后的进程,您可以使用内核内分配器分配一个或更多帧,并将堆栈设置为指向它的结尾(在递减堆栈的情况下)。这个来自another kernel 的示例显示了为新进程设置堆栈所做的工作(这高度依赖于实际的内核/任务切换代码)。 (在这种情况下,没有动态分配的内存,因为它在嵌入式场景中使用)。

    【讨论】:

    • 我明白了!但是仍然 - 为了调用您的 kmalloc 函数,函数的堆栈框架必须有一个调用堆栈,对吗?编译后的函数是否使用(和管理)堆栈寄存器,这样操作系统基本上只需要初始化堆栈段/指针寄存器?
    【解决方案2】:

    操作系统需要为自己(内核)和用户管理内存。

    您似乎在询问用户内存管理。这是通过管理分配给进程的页面来完成的。堆栈是通过分配页面进程来管理的。

    堆内存管理(如 malloc)分两部分完成。为操作系统内核提供系统服务以将页面映射到进程。其次,库管理在这些页面中创建的一个或多个内存池。

    【讨论】:

      猜你喜欢
      • 2016-07-12
      • 1970-01-01
      • 2021-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多