当说3个程序(可执行文件)加载到内存中时,布局可能如下所示:
alt text http://img97.imageshack.us/img97/3460/processesm.jpg
我有以下问题:
虚拟内存的概念是否仅限于用户进程?因为,我想知道操作系统内核,驱动程序在哪里?它的内存布局如何?我想更多地了解内核端内存。我知道它的操作系统特定的选择(windows / linux)。
每个进程的虚拟内存概念是什么?我的意思是说我说4GB的进程1 + 4GB的进程2 + 4GB的进程3 = 12GB的虚拟内存(对于所有进程)是正确的。这听起来不对。或者从总共4GB的空间中获取内核和1GB的1GB空间。剩下的3GB是所有进程共享的。
他们说,在4GB地址空间的32位机器上。其中一半(或最近1GB)被内核占用。我在这个图中可以看到“内核虚拟内存”占用0xc0000000 - 0xffffffff(= 1 GB)。他们在谈论这个吗?或者是别的什么?只是想确认一下。
每个进程的Kernel Virtual Memory
包含哪些完全?它的布局是什么?
当我们做IPC时,我们谈论共享内存。我没有看到这些进程之间共享任何内存。它住在哪里?
资源(Windows中的文件,注册表)对所有进程都是全局的。因此,资源/文件句柄表必须位于某个全局空间中。那个区域会是什么?
我在哪里可以了解更多有关此内核方面的内容。
答案 0 :(得分:22)
当系统使用虚拟内存时,内核也会使用虚拟内存。 Windows将使用高2GB(如果您在Windows引导加载程序中指定了/ 3GB开关,则为1GB)供自己使用。这包括内核代码,数据(或者至少是分页的数据 - 这是正确的,Windows可以将部分内核地址空间分页到硬盘)和页表。
每个进程都有自己的VM地址空间。发生进程切换时,页表通常会与另一个进程的页表交换出来。这在x86处理器上很简单 - 更改CR3
控制寄存器中的页表基址就足够了。整个4GB地址空间被替换为完全不同的4GB地址空间的表替换。话虽如此,通常会有进程间共享的地址空间区域。这些区域在页面表中标记有特殊标记,这些标记向处理器指示这些区域不需要在处理器translation lookaside buffer中无效。
正如我前面提到的,内核的代码,数据和页表本身需要位于某处。此信息位于内核地址空间中。内核的代码,数据和页表的某些部分可能会根据需要自行交换到磁盘。有些部分被认为比其他部分更重要,根本不会被换掉。
见(3)
这取决于。用户模式共享内存位于用户模式地址空间中。内核模式地址空间的一部分也可以在进程之间共享。例如,内核的代码在系统中的所有进程之间共享并不罕见。记忆所在的地方并不精确。我在这里使用任意地址,但是在一个进程中位于0x100000
的共享内存可能位于另一个进程内的0x101000
。不同地址空间中的两个页面,位于完全不同的地址,可以指向相同的物理内存。
我不确定你的意思。打开文件句柄对于所有进程都不是全局的。存储在硬盘上的文件系统对所有进程都是全局的。在Windows下,文件句柄由内核管理,对象存储在内核地址空间中,由内核对象管理器管理。
对于基于Windows NT的系统,我建议使用Mark Russinovich和David Solomon的Windows Internals, 5ed
对评论的回应:
现在这3GB是共享的 流程?或者每个进程都有4GB 空间?
这取决于操作系统。某些内核(例如L4
microkernel)对多个进程使用相同的页表,并使用segmentation分隔地址空间。在Windows上,每个进程都有自己的页表。请记住,即使每个进程都可能获得自己的虚拟地址空间,但这并不意味着物理内存始终不同。例如,进程A中加载的kernel32.dll
映像在进程B中与kernel32.dll
共享。大部分内核地址空间也在进程之间共享。
为什么每个进程都有内核 虚拟内存?
想到这一点的最好方法是问自己,“如果内核没有使用虚拟内存执行,内核将如何工作?”在这种假设的情况下,每当您的程序导致上下文切换到内核时(假设您进行了系统调用),当CPU在内核空间中执行时,必须禁用虚拟内存。这样做是有代价的,当你切换回用户空间时需要重新开启它。
此外,假设用户程序传入指向其系统调用的某些数据的指针。该指针是一个虚拟地址。您已关闭虚拟内存,因此在内核可以对其执行任何操作之前,需要将指针转换为物理地址。如果您打开了虚拟内存,由于CPU上的内存管理单元,您可以免费获得。相反,您必须手动翻译软件中的地址。我可以描述各种各样的示例和场景(一些涉及硬件,一些涉及页面表维护,等等),但其要点是拥有一个同类内存管理方案要容易得多。如果用户空间正在使用虚拟内存,那么如果在内核空间中维护该方案,则编写内核会更容易。至少这是我的经历。
只有一个OS的实例 内核对吗?然后为什么每个过程 有单独的内核虚拟空间吗?
正如我上面提到的,相当多的地址空间将在进程间共享。内核空间中存在每个进程数据,这些数据在进程之间的上下文切换期间被换出,但是由于只有一个内核,所以会共享大量数据。
答案 1 :(得分:3)
要回答您的问题,您需要了解更多有关内核及其用于管理资源(CPU,内存,...)以及为应用程序提供优雅抽象的技术。
首先,我想明确表示' 虚拟内存'是现代操作系统采用的内存管理技术;它提供了各种好处,如进程隔离,通过保护,允许多个程序一起运行,允许程序的大小大于系统中存在的物理内存。 在这种技术下,又有两个术语'虚拟内存'和'虚拟地址空间&#39 ;;哪些不一样,但仍然密切相关。 (你会想知道虚拟内存如何既是一种技术也是一种概念,但是这是正确的,你将在下面理解)
在计算机科学中,“记忆'有2个含义。第一个是用于存储数据(寄存器,缓存,RAM,ROM,HDD等)的东西。第二个是与主存储器同义(即 RAM )。 当您逐字替换时,'虚拟内存'只不过是虚拟 RAM '。这是系统中始终可用的总空间量,其中加载程序以供执行。所以这只是物理RAM内存+内核分配的辅助存储器上的交换内存。 因此,如果在安装时内核预留了2GB的RAM和4 GB的交换空间,那么系统的虚拟内存为6GB。我不会在这里解释有关交换内存的更多信息,因为这会偏离主题。
转到虚拟地址空间。 所以要理解这一点,你需要调整一下你的思想。正如名称本身"虚拟"说,地址空间不存在于现实中!这只是内核为应用程序员创建的幻觉(如我在第2段中提到的那样实现了很多好处) 因此内核为每个进程提供了一个单独的虚拟地址空间。 (如果系统中没有内核并且您在硬件上运行应用程序,那么它将使用物理地址空间,即RAM作为其地址空间) 因此,在具有32位地址寄存器的机器上,内核可以为每个进程提供2 ^ 32 = 4GB的虚拟地址空间。 (因此,此虚拟地址空间范围随HW架构而变化。最新处理器具有48位地址寄存器,因此它们可提供2 ^ 48 = 256TB的虚拟地址空间) 而且重要的是这个虚拟地址空间就在空中!! 你现在会想到,如果只是在空中,那么如何才能执行代码,进程数据。是的,这需要映射到物理内存。如何与物理内存映射由内核使用称为分页的概念进行管理。 现在,您可以看到内核如何使用虚拟地址空间实现进程隔离。因此,每个进程可以生成的地址介于0到4GB之间(假设系统具有32位地址寄存器,为简单起见),因此这是完整的。它对系统中运行的任何其他进程一无所知。因此,就像每个进程都包含在一个单独的空间中一样。
因此内核代码也像另一个进程/实体。因此,如果内核驻留在完全不同的地址空间中。然后,应用程序无法与内核交互。如果应用程序无法与内核通信,并且内核无法与应用程序通信,那么内核驱动系统就没有用处。 所以现在的问题是 - 如何使应用程序进程与内核交互? 一个选项是 - 如果内核代码存在于应用程序进程的虚拟地址空间中,那么它们可以相互交互。这就是为什么内核代码存在于每个进程中的原因'虚拟地址空间,因为每个进程都需要与内核通信。不要担心内核代码在每个进程中都不会物理复制。正如我前面提到的,VAS只是一种幻觉,因此在物理内存中只会出现一个内核代码副本,它将被所有虚拟地址空间引用(通过分页)。 在linux的情况下,内核将被放置在C000 0000到FFFF FFFF之间的高位地址空间(即,在VAS中为内核保留1GB的原因)并且允许应用程序使用3GB(从0000 0000到BFFF FFFF)使用。内核所在的虚拟地址空间称为内核空间,应用程序所在的位置称为用户空间。 如果您仔细观察过,那么您会想到如果应用程序代码和内核代码都驻留在同一个虚拟地址空间中,并且由于内核位于预先定义好的地址位置,那么就不可能了用于破坏内核代码的应用程序代码!哎呀,起初它看起来是可能的,但它不可能。 原因是 - 这是在HW的帮助下保护的。处理器上会有标志,指示执行模式是SUPERVISOR MODE还是USER MODE。内核空间代码应在SUPERVISOR MODE中执行(适当地设置该标志),用户空间代码应在USER MODE中执行。因此,如果您处于USER MODE并尝试访问/修改内核空间中的代码,则会抛出异常! (处理器根据指令试图访问的地址来了解它。如果它高于C000 0000则可以很容易地检测到它正在尝试访问内核空间代码并且当前执行模式没有适当的权限,因为该标志是用USER MODE权限设置的)。请注意:在SUPERVISOR模式下,处理器可以访问附加的指令集。
我希望如果您理解这个概念,您可以回答自己的问题。在解释概念本身时,我直接回答了你的许多问题。