操作系统内核和主内存中的进程

Mar*_*ark 12 c linux ram operating-system kernel

继续我在操作系统开发研究方面的努力,我已经构建了一个几乎完整的图片.还有一件事让我望而却步.

根据我的理解,这是基本的启动过程:

1)BIOS/Bootloader执行必要的检查,初始化所有内容.

2)内核加载到RAM中.

3)内核执行其初始化并开始调度任务.

4)加载任务时,会为其提供一个虚拟地址空间.包括.text,.data,.bss,堆和堆栈.此任务"维护"自己的堆栈指针,指向其自己的"虚拟"堆栈.

5)上下文切换仅将寄存器文件(所有CPU寄存器),堆栈指针和程序计数器推入某个内核数据结构,并加载另一个属于另一个进程的集合.

在这个抽象中,内核是一个"母"过程,其中所有其他进程都是托管的.我试图在下图中表达我最好的理解:

在此输入图像描述

问题是,首先这个简单的模型是否正确?

其次,可执行程序如何识别其虚拟堆栈?是OS作业来计算虚拟堆栈指针并将其放在相关的CPU寄存器中吗?堆栈簿记的其余部分是由CPU弹出和推送命令完成的吗?

内核本身是否有自己的主堆栈和堆?

谢谢.

Dan*_*ein 9

问题是,首先这个简单的模型是否正确?

您的模型非常简化,但基本上是正确的 - 请注意,模型的最后两部分并不真正被认为是引导过程的一部分,而内核不是一个过程.将它可视化为一个可能很有用,但它不适合过程的定义,并且它不像一个过程.

其次,可执行程序如何识别其虚拟堆栈?是OS作业来计算虚拟堆栈指针并将其放在相关的CPU寄存器中吗?堆栈簿记的其余部分是由CPU弹出和推送命令完成的吗?

可执行的C程序不必"了解其虚拟堆栈".当C程序编译成可执行文件时,通常会相对于堆栈指针引用局部变量 - 例如,[ebp - 4].

当Linux加载新程序以执行时,它使用start_thread宏(从load_elf_binary调用)来初始化CPU的寄存器.该宏包含以下行:

regs->esp = new_esp;   
Run Code Online (Sandbox Code Playgroud)

这会将CPU的堆栈指针寄存器初始化为OS分配给线程堆栈的虚拟地址.

正如您所说,一旦加载了堆栈指针,诸如pop和之类的汇编命令push将更改其值.操作系统负责确保存在与虚拟堆栈地址对应的物理页面 - 在使用大量堆栈内存的程序中,随着程序继续执行,物理页面的数量将增加.使用该ulimit -a命令可以找到每个进程的限制(在我的机器上,最大堆栈大小为8MB,或2KB页面).

内核本身是否有自己的主堆栈和堆?

这是将内核可视化为进程可能会变得混乱的地方.首先,Linux中的线程具有用户堆栈和内核堆栈.它们基本相同,仅在保护和位置上有所不同(在内核模式下执行时使用内核堆栈,在用户模式下执行时使用用户堆栈).

内核本身没有自己的堆栈.内核代码总是在某个线程的上下文中执行,每个线程都有自己的固定大小(通常是8KB)内核堆栈.当线程从用户模式移动到内核模式时,CPU的堆栈指针会相应更新.因此,当内核代码使用局部变量时,它们存储在它们正在执行的线程的内核堆栈中.

在系统启动期间,start_kernel函数初始化内核init线程,然后内核线程将创建其他内核线程并开始初始化用户程序.因此在系统启动后,CPU的堆栈指针将被初始化为指向init内核堆栈.

就堆而言,您可以使用内核动态分配内存kmalloc,这将尝试在内存中查找空闲页面 - 其内部实现使用get_zeroed_pa​​ge.

  • *"内核本身没有自己的堆栈."*虽然没有错误,但我认为这一点从我的回答中清除了OP的误解:*"虽然内核可能有自己的线程,......内核不应该'真的被认为是一个独立运行的"母进程"......"*这里的关键点:**线程(任务)有堆栈**,以及用户模式进程和内核线程(又名`kthread` in Linux)是线程.此外,用户模式线程实际上会有多个堆栈:一个在用户模式下,另一个在内核中. (3认同)

Jon*_*art 8

你忘了一个重要的观点:虚拟内存由硬件执行,通常被称为MMU(内存管理单元).MMU将虚拟地址转换为物理地址.

内核通常将特定进程的页表的基地址加载到MMU中的寄存器中.这就是任务 - 将虚拟内存空间从一个进程切换到另一个进程.在x86上,这个寄存器是CR3.

虚拟内存可以保护进程的内存.进程A的RAM根本没有映射到进程B(除了例如共享库,其中相同的代码存储器被映射到多个进程,以节省内存).

虚拟内存还可以保护内核内存空间免受用户模式进程的影响.设置覆盖内核地址空间的页面上的属性,以便当处理器在用户模式下运行时,不允许在那里执行.

请注意,虽然内核可能拥有自己的线程(完全在内核空间中运行),但内核不应该被认为是独立于用户模式程序运行的"母进程".内核基本上用户模式程序的"另一半"!无论何时发出系统调用,CPU都会自动转换为内核模式,并在内核指定的预定义位置开始执行.然后,内核系统调用处理程序代表您在进程的内核模式上下文中执行.在内核中处理您的请求所花费的时间会被计算在内,并"收取"您的流程.