【问题标题】:Location of OS Kernel Data操作系统内核数据的位置
【发布时间】:2019-06-02 16:45:04
【问题描述】:

我是操作系统的初学者,我有一个关于操作系统内核的问题。

我习惯于每个用户进程都有一个由堆栈、堆、数据和代码组成的虚拟地址空间的标准概念。我的问题是,当操作系统内核发生上下文切换时,内核中运行的代码是否被视为具有堆栈、堆、数据和代码的进程?

我知道有一个专用的内核堆栈,用户程序无法访问它。这是否位于用户程序地址空间中?

我知道操作系统需要维护一些数据结构才能完成其工作,例如进程控制块。这些数据结构在哪里?它们在用户程序地址空间中吗?它们是否在内核数据结构的某个专用内存段中?它们是否分散在任何有空间的物理内存周围?

最后,我看到了一些图表,其中操作系统代码位于用户程序地址空间的顶部。整个操作系统内核都位于这里吗?如果不是,操作系统内核的代码还驻留在哪里?

感谢您的帮助!

【问题讨论】:

  • 您可以通过以 root 身份从文件 /proc/iomem 读取来找到内核代码和数据的地址。 sudo cat /proc/iomem | grep Kernel

标签: operating-system location kernel heap-memory stack-memory


【解决方案1】:

是的,内核有自己的堆栈、堆、数据结构和代码,独立于每个用户进程。

在内核中运行的代码本身并不被视为“进程”。代码是特权,这意味着它可以修改内核中的任何数据,在处理器寄存器中设置特权位,发送中断,与设备交互,执行特权指令等。它不像代码中的代码那样受到限制用户进程。

所有内核内存和用户进程内存都存储在计算机的物理内存中(如果数据已从内存中交换,则可能存储在磁盘上)。

回答其余问题的关键是了解物理内存和虚拟内存之间的区别。请记住,如果您使用虚拟内存地址来访问数据,则在从确定的物理地址获取数据之前,该虚拟地址会被转换为物理地址。

每个进程都有自己的虚拟地址空间。这意味着一个进程中的某个虚拟地址 a 可以映射到与另一个进程中的相同虚拟地址 a 不同的物理地址。虚拟内存有很多重要的用途,但我不打算在这里讨论它们。重要的一点是虚拟内存强制执行内存隔离。这意味着进程 A 无法访问进程 B 的内存。进程 A 的所有虚拟地址都映射到一组物理地址,而进程 B 的所有虚拟地址都映射到另一组物理地址。只要两组物理地址不重叠,进程就无法看到或修改彼此的内存。用户进程不能直接访问物理内存地址——它们只能使用虚拟地址进行内存访问。

有时两个进程可能有一些虚拟地址映射到相同的物理地址,例如如果它们都映射同一个文件,都使用共享库等。

现在回答您关于内核地址空间和用户地址空间的问题。

内核可以有一个独立于每个用户进程的虚拟地址空间。这就像在每次上下文切换时更改 cr3 寄存器(在 x86 处理器中)中的页面目录指针一样简单。由于内核具有不同的虚拟地址空间,因此只要内核的虚拟内存地址都没有映射到与用户进程的任何地址空间中的任何虚拟地址相同的物理地址,任何用户进程都无法访问内核内存。

这可能会导致一个小问题。如果用户进程进行系统调用并将指针作为参数传递(例如,read 系统调用中指向缓冲区的指针),内核如何知道哪个物理地址对应于该缓冲区?指针中的虚拟地址映射到内核空间中的不同物理地址,因此内核不能仅仅取消引用指针。有两种选择:

  1. 内核可以遍历用户进程页目录/表来找到缓冲区对应的物理地址。然后内核可以读取/写入该物理地址。

  2. 内核可以将其所有映射包含在用户地址空间中(如您所述,位于用户地址空间的顶部)。现在,当内核通过系统调用接收到一个指针时,它可以直接访问指针,因为它与进程共享地址空间。

内核通常采用第二种选择,因为它更方便、更高效。选项 1 效率较低,因为每次发生上下文切换时,地址空间都会发生变化,因此需要刷新 TLB,现在您会丢失所有缓存的映射。由于最近发现的 Meltdown 漏洞,内核已经开始以不同的方式做事,所以我在这里简化了一些事情。

这会导致另一个问题。如果内核在用户进程地址空间中包含它的映射,是什么阻止用户进程访问内核内存?内核在页表中设置保护位,导致处理器禁止用户进程访问映射到包含内核内存的物理地址的虚拟地址。

查看这些slides 了解更多信息。

【讨论】:

    【解决方案2】:

    我习惯于每个用户进程都有一个由堆栈、堆、数据和代码组成的虚拟地址空间的标准概念。我的问题是,当操作系统内核发生上下文切换时,内核中运行的代码是否被视为具有堆栈、堆、数据和代码的进程?

    据我所知,每一个现代操作系统都没有上下文切换到内核。内核在进程上下文中执行(某些系统使用简化的进程上下文的虚构。

    “内核”在进程通过异常或中断进入内核模式时执行。

    每个进程(线程)通常在发生异常后都有自己的内核模式堆栈。通常每个处理器都有一个单独的中断堆栈。

    https://books.google.com/books?id=FSX5qUthRL8C&pg=PA322&lpg=PA322&dq=vax+%22interrupt+stack%22&source=bl&ots=CIaxuaGXWY&sig=S-YsXBR5_kY7hYb6F2pLGjn5pn4&hl=en&sa=X&ved=2ahUKEwjrgvyX997fAhXhdd8KHdT7B8sQ6AEwCHoECAEQAQ#v=onepage&q=vax%20%22interrupt%20stack%22&f=false

    我知道有一个专用的内核堆栈,用户程序无法访问它。这是否位于用户程序地址空间中?

    每个进程都有自己的内核栈。它通常位于具有受保护内存的用户空间中,但也可能位于系统空间中。中断堆栈始终在系统空间中。

    这些数据结构位于何处?它们在用户程序地址空间中吗?

    它们通常在系统空间中。但是,有些系统确实将用户空间中的一些结构放入受保护的内存中。

    它们是否在内核数据结构的某个专用内存段中?

    如果它们在用户空间中,它们通常用于比用户模式具有更高特权但比内核模式具有更低特权的访问模式。

    它们是否分散在任何有空间的物理内存周围?

    想法几乎可以随机分布在物理内存中。

    【讨论】:

      猜你喜欢
      • 2016-10-21
      • 2011-09-13
      • 1970-01-01
      • 2014-05-27
      • 2012-04-24
      • 2010-10-27
      • 2011-11-17
      • 2012-03-02
      • 1970-01-01
      相关资源
      最近更新 更多