每个进程的内核虚拟内存包含什么?

cla*_*aws 22 assembly linker operating-system loader

当说3个程序(可执行文件)被加载到内存中时,布局可能如下所示:

alt text http://img97.imageshack.us/img97/3460/processesm.jpg

我有以下问题:

  1. 虚拟内存的概念是否仅限于用户进程?因为,我想知道操作系统内核,驱动程序在哪里?它的内存布局如何?我想更多地了解内核端内存.我知道它的操作系统特定的选择(windows/linux).

  2. 是每个进程虚拟内存的概念吗?我的意思是说我说4GB的进程1 + 4GB的进程2 + 4GB的进程3 = 12GB的虚拟内存(对于所有进程)是正确的.这听起来不对.或者从总共4GB空间内核占用1GB,其余3GB共享b/w所有进程.

  3. 他们说,在4GB地址空间的32位机器上.其中一半(或最近1GB)被内核占用.我在这个图中可以看到"内核虚拟内存"占用0xc0000000 - 0xffffffff(= 1 GB).他们在谈论这个吗?或者是别的什么?只是想确认一下.

  4. 什么究竟做了Kernel Virtual Memory每个流程的内容?它的布局是什么?

  5. 当我们做IPC时,我们谈论共享内存.我没有看到这些进程之间共享任何内存.它在哪里生活?

  6. 资源(Windows中的文件,注册表)对所有进程都是全局的.因此,资源/文件句柄表必须位于某个全局空间中.那个区域会是什么?

  7. 我在哪里可以更多地了解这个内核方面的东西.

Aar*_*otz 25

  1. 当系统使用虚拟内存时,内核也使用虚拟内存.Windows将使用高2GB(如果您在Windows引导加载程序中指定了/ 3GB开关,则为1GB)供自己使用.这包括内核代码,数据(或者至少是分页的数据 - 正确,Windows可以将部分内核地址空间分页到硬盘)和页表.

  2. 每个进程都有自己的VM地址空间.发生进程切换时,页表通常会与另一个进程的页表交换出来.这在x86处理器上很简单 - 更改CR3控制寄存器中的页表基址就足够了.整个4GB地址空间被替换为完全不同的4GB地址空间的表替换.话虽如此,通常会有进程间共享的地址空间区域.这些区域在页表中标记有特殊标志,这些标志向处理器指示在处理器的转换后备缓冲区中不需要使这些区域无效.

  3. 正如我之前提到的,内核的代码,数据和页表本身需要位于某处.此信息位于内核地址空间中.内核的代码,数据和页表的某些部分可能会根据需要自行交换到磁盘.有些部分被认为比其他部分更重要,并且根本不会被换掉.

  4. 见(3)

  5. 这取决于.用户模式共享内存位于用户模式地址空间中.内核模式地址空间的一部分也可以在进程之间共享.例如,内核的代码在系统中的所有进程之间共享并不罕见.记忆所在的地方并不精确.我在这里使用任意地址,但位于0x100000一个进程中的共享内存可能位于0x101000另一个进程内部.不同地址空间中的两个页面,在完全不同的地址,可以指向相同的物理内存.

  6. 我不确定你的意思.打开文件句柄对于所有进程都不是全局的.存储在硬盘上的文件系统对所有进程都是全局的.在Windows下,文件句柄由内核管理,对象存储在内核地址空间中,由内核对象管理器管理.

  7. 对于基于Windows NT的系统,我推荐由Mark Russinovich和David Solomon提供的Windows Internals

回复评论:

现在这个3GB是否共享b/w所有进程?或者每个进程有4GB空间?

这取决于操作系统.某些内核(例如L4微内核)对多个进程使用相同的页表,并使用分段分隔地址空间.在Windows上,每个进程都有自己的页表.请记住,即使每个进程都可能获得自己的虚拟地址空间,但这并不意味着物理内存总是不同的.例如,kernel32.dll进程A中加载的映像在进程B中共享kernel32.dll.许多内核地址空间也在进程之间共享.

为什么每个进程都有内核虚拟内存?

想到这一点的最好方法是问自己,"如果内核没有使用虚拟内存执行,内核将如何工作?" 在这种假设的情况下,每当您的程序导致上下文切换到内核时(假设您进行了系统调用),当CPU在内核空间中执行时,必须禁用虚拟内存.这样做需要付出代价,当您切换回用户空间时需要重新打开它.

此外,假设用户程序传入指向其系统调用的某些数据的指针.该指针是一个虚拟地址.您已关闭虚拟内存,因此在内核可以对其执行任何操作之前,需要将指针转换为物理地址.如果您打开了虚拟内存,由于CPU上的内存管理单元,您可以免费获得.相反,您必须手动翻译软件中的地址.我可以描述各种示例和场景(一些涉及硬件,一些涉及页面表维护,等等),但其要点是,拥有一个同类内存管理方案要容易得多.如果用户空间正在使用虚拟内存,那么如果在内核空间中维护该方案,则编写内核会更容易.至少那是我的经历.

OS内核只有一个实例吗?那为什么每个进程都有独立的内核虚拟空间?

正如我上面提到的,相当多的地址空间将在进程间共享.内核空间中存在每个进程数据,这些数据在进程之间的上下文切换期间被换出,但由于只有一个内核,因此共享大量数据.


Dar*_*n L 11

要回答您的问题,您需要更多地了解内核及其用于管理资源(CPU、内存等)并为应用程序提供优雅抽象的技术。

首先,我想说明“虚拟内存”是现代操作系统采用的一种内存管理技术;它提供了各种好处,例如进程隔离,通过保护,允许多个程序一起运行,允许大小大于系统中存在的物理内存的程序。在这种技术下,同样有两个术语“虚拟内存”和“虚拟地址空间”;它们不一样,但仍然密切相关。(您会想知道虚拟内存如何既是一种技术又是其下的概念,但是是的,这是正确的,您将在下面理解)

在计算机科学中,“内存”这个词有两个含义。第一个是用于存储数据的东西(寄存器、缓存、RAM、ROM、HDD 等)。第二个是与主内存(即RAM)同义的。当您逐字替换时,“虚拟内存”只不过是“虚拟内存RAM”'。这是系统中始终可用的空间总量,程序在其中加载以执行。所以这只不过是物理 RAM 内存 + 内核分配的辅助存储上的交换内存。因此,如果内核在安装时预留了 2GB 的 RAM 和 4GB 的交换空间,则系统的虚拟内存为 6GB。我不会在这里解释更多关于交换内存的内容,因为这会偏离主题。

转到虚拟地址空间。因此,要理解这一点,您需要稍微调整一下自己的思想。正如名称本身“虚拟”所说,地址空间在现实中并不存在!这只是内核对应用程序程序员的一种错觉(为了实现我在第 2 段中提到的很多好处),因此内核为每个进程分配了一个单独的虚拟地址空间。(如果系统中没有内核,并且你在硬件上运行你的应用程序,那么它就会使用物理地址空间,即 RAM 作为它的地址空间)所以在具有 32 位地址寄存器的机器上,内核可以为每个进程提供 2^32 = 4GB 的虚拟地址空间。(所以这个虚拟地址空间范围随着硬件架构的变化而变化。 重要的是,这个虚拟地址空间只是在空中!!你现在会想,如果只是在空中,流程的代码、数据怎么可能被执行。是的,这需要映射到物理内存。它如何与物理内存映射由内核使用称为分页的概念进行管理。所以现在你可以看到内核是如何使用虚拟地址空间实现进程隔离的。所以每个进程可以生成的地址在 0 到 4GB 之间(为了简单起见,假设系统有 32 位地址寄存器),所以这是它的全部内容。它对系统中运行的任何其他进程一无所知。所以就好像每个进程都被包装在一个单独的空间中。

所以内核代码也像另一个进程/实体。因此,如果内核要驻留在完全不同的地址空间中。那么应用程序就无法与内核进行交互。如果应用程序不能与内核通信,内核不能与应用程序通信,那么内核驱动系统就没有用处。那么现在的问题是——如何让应用进程与内核交互? 一个选项是 - 如果内核代码存在于应用程序进程的虚拟地址空间中,那么它们可以相互交互。这就是内核代码存在于每个进程的虚拟地址空间中的原因,因为每个进程都需要与内核通信。不要担心内核代码不会为每个进程物理复制。正如我之前提到的,VAS 只是一种幻觉,因此物理内存中只会存在内核代码的一个副本,并且所有虚拟地址空间都将引用它(通过分页)。在 linux 的情况下,内核将被放置在 C000 0000 到 FFFF FFFF 之间的上层地址空间(即 VAS 中为内核保留 1GB 的原因),其余 3GB(从 0000 0000 到 BFFF FFFF)允许应用程序用。内核所在的虚拟地址空间称为内核空间,应用程序所在的虚拟地址空间称为用户空间。如果您仔细观察,那么您会提出这样的问题:如果应用程序代码和内核代码都驻留在同一个虚拟地址空间中,并且由于内核驻留在一个预先定义好的地址位置,那么这是不可能的为应用程序代码破坏内核代码!哎呀,一开始看起来是可能的,但它不能。原因是 - 这在硬件的帮助下受到保护。处理器上会有标志,指示执行模式是SUPERVISOR MODE 还是USER MODE。内核空间代码应该在 SUPERVISOR MODE(适当设置该标志)下执行,而用户空间代码应该在 USER MODE 下执行。因此,如果您处于用户模式并尝试访问/修改内核空间中的代码,则会引发异常!(处理器根据指令试图访问的地址知道它。如果它高于 C000 0000 那么它可以很容易地检测到它正在尝试访问内核空间代码并且当前的执行模式没有适当的权限,因为该标志是使用 USER MODE 权限设置的)。请注意:在 SUPERVISOR 模式下,处理器提供对附加指令集的访问。因为该标志是使用 USER MODE 权限设置的)。请注意:在 SUPERVISOR 模式下,处理器提供对附加指令集的访问。因为该标志是使用 USER MODE 权限设置的)。请注意:在 SUPERVISOR 模式下,处理器提供对附加指令集的访问。

我希望如果你理解这个概念,你就可以回答你的问题。我在解释概念本身的同时直接回答了您的许多问题。


Iza*_*ana 5

引用自csapp 第 3 章第 9 章:

\n

在此输入图像描述

\n
\n

内核虚拟内存包含内核中的代码和数据结构。内核虚拟内存的某些区域被映射到由所有进程共享的物理页。例如,每个进程共享kernel\xe2\x80\x99s代码和全局数据结构。有趣的是,Linux还将一组连续的虚拟页面(大小等于系统中DRAM的总量)映射到相应的一组连续的物理页面。这为内核提供了一种方便的方式来访问物理内存\xe2\x80\x94中的任何特定位置,例如,当它需要访问页表或在映射到特定物理内存的设备上执行内存映射I/O操作时地点。

\n

内核虚拟内存的其他区域包含每个进程不同的数据。示例包括页表、内核在进程上下文中执行代码时使用的堆栈,以及跟踪虚拟地址空间当前组织的各种数据结构。

\n
\n

在此输入图像描述

\n

每个进程的示例数据结构task_struct

\n

还为每个进程存储上下文切换所需的进程上下文。

\n
\n

它由通用寄存器、浮点寄存器、程序计数器、user\xe2\x80\x99s 堆栈、状态寄存器、kernel\xe2\x80\x99s 堆栈和各种内核数据等对象的值组成诸如表征地址空间的页表、包含有关当前进程 (PID) 的信息的进程表以及包含有关进程已打开的文件的信息的文件表等结构。

\n
\n

信号位向量也被存储。

\n
\n

相关答案

\n
\n
    \n
  1. 每个进程都有自己的内核堆栈吗?
  2. \n
\n

不仅仅是每个进程 - 每个线程都有自己的内核堆栈(实际上,还有自己的用户堆栈)。请记住,进程和线程(对于 Linux)的唯一区别是多个线程可以共享地址空间(形成进程)。

\n
\n