Nei*_*rni 4 location operating-system kernel heap-memory stack-memory
我是操作系统的初学者,我有一个关于操作系统内核的问题。
我习惯于每个用户进程都有一个堆栈、堆、数据和代码的虚拟地址空间的标准概念。我的问题是,当操作系统内核发生上下文切换时,内核中运行的代码是否被视为具有堆栈、堆、数据和代码的进程?
我知道有一个专用的内核堆栈,用户程序无法访问它。它是否位于用户程序地址空间中?
我知道操作系统需要维护一些数据结构才能完成它的工作,比如进程控制块。这些数据结构位于何处?它们是否在用户程序地址空间中?它们是否在内核数据结构的某个专用内存段中?它们是否散布在有空间的物理内存周围?
最后,我看到了一些图表,其中操作系统代码位于用户程序地址空间的顶部。整个操作系统内核都在这里吗?如果没有,操作系统内核的代码还驻留在何处?
谢谢你的帮助!
是的,内核有自己的栈、堆、数据结构和代码,与每个用户进程的那些分开。
在内核中运行的代码本身不被视为“进程”。特权代码意味着它可以修改内核中的任何数据、设置处理器寄存器中的特权位、发送中断、与设备交互、执行特权指令等。它不像用户进程中的代码那样受到限制。
所有内核内存和用户进程内存都存储在计算机的物理内存中(如果数据已从内存中交换,则可能存储在磁盘上)。
回答其余问题的关键是了解物理内存和虚拟内存之间的区别。请记住,如果您使用虚拟内存地址来访问数据,那么在确定的物理地址获取数据之前,该虚拟地址会被转换为物理地址。
每个进程都有自己的虚拟地址空间。这意味着一个进程中的某个虚拟地址a可以映射到与另一个进程中相同虚拟地址a不同的物理地址。虚拟内存有许多重要的用途,但我不打算在此详细介绍。重要的一点是虚拟内存强制执行内存隔离. 这意味着进程 A 不能访问进程 B 的内存。进程 A 的所有虚拟地址都映射到某些物理地址集,而进程 B 的所有虚拟地址映射到不同的物理地址集。只要两组物理地址不重叠,进程就不能看到或修改彼此的内存。用户进程不能直接访问物理内存地址——它们只能使用虚拟地址进行内存访问。
有时两个进程可能有一些虚拟地址确实映射到相同的物理地址,例如如果它们都映射同一个文件,都使用共享库等。
所以现在回答你关于内核地址空间和用户地址空间的问题。
内核可以有一个独立于每个用户进程的虚拟地址空间。这就像cr3在每次上下文切换时更改寄存器(在 x86 处理器中)中的页目录指针一样简单。由于内核具有不同的虚拟地址空间,只要内核的虚拟内存地址中没有一个映射到与用户进程的任何地址空间中的任何虚拟地址相同的物理地址,任何用户进程都不能访问内核内存。
这可能会导致一个小问题。如果用户进程进行系统调用并传递一个指针作为参数(例如read系统调用中指向缓冲区的指针),内核如何知道哪个物理地址对应于该缓冲区?指针中的虚拟地址映射到内核空间中的不同物理地址,因此内核不能只是取消引用指针。有两种选择:
内核可以遍历用户进程页目录/表,找到缓冲区对应的物理地址。然后内核可以从/向该物理地址读取/写入。
内核可以将其所有映射包含在用户地址空间中(如您所述,位于用户地址空间的顶部)。现在,当内核通过系统调用接收到一个指针时,它可以直接访问该指针,因为它与进程共享地址空间。
内核通常采用第二种选择,因为它更方便、更高效。选项 1 效率较低,因为每次发生上下文切换时,地址空间都会发生变化,因此需要刷新 TLB,现在您会丢失所有缓存的映射。鉴于最近发现的 Meltdown 漏洞,内核已经开始以不同的方式做事,因此我在这里稍微简化了一些事情。
这会导致另一个问题。如果内核在用户进程地址空间中包含了它的映射,是什么阻止了用户进程访问内核内存?内核在页表中设置保护位,使处理器禁止用户进程访问映射到包含内核内存的物理地址的虚拟地址。
查看这些幻灯片以获取更多信息。
| 归档时间: |
|
| 查看次数: |
1988 次 |
| 最近记录: |