为什么内核需要虚拟地址?

25
在Linux中,每个进程都有它自己的虚拟地址空间(例如32位系统中的4 GB,其中3GB是给进程使用的,1 GB是给内核使用的)。这种虚拟寻址机制有助于隔离每个进程的地址空间。对于进程而言,由于有很多进程,因此这是可以理解的。但既然我们只有一个内核,为什么我们还需要内核的虚拟寻址呢?

5
我认为你可能想阅读这篇文章:http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory - Mithrandir
内核可能有自己的内存映射,但在Linux内核中,数据不会被分页。请参阅http://en.wikipedia.org/wiki/Virtual_memory和http://en.wikipedia.org/wiki/Linux_kernel。 - Basile Starynkevitch
2个回答

20

内核被称为“虚拟”的原因不是为了处理分页,而是因为处理器一次只能运行在一种模式下。所以一旦打开分页内存映射(x86上CR0中的第31位),处理器就期望所有内存访问都通过页面映射机制进行。因此,既然我们希望即使在启用分页(虚拟内存)后仍然可以访问内核,它就需要存在于虚拟空间中。

“保留”内存更多是出于“容易确定地址是内核还是用户空间”的考虑,而不是其他任何方面。完全有可能将内核的一小部分放在地址12345-34121处,将另一部分内核放在101900-102400处,将其他一部分内核放在40000000-40001000处。但这会让内核和用户空间的每个方面都变得困难 - 必须处理间隙/空洞[已经存在这样的空洞,但有更多也不会有所帮助]。通过设置一个固定的限制,即“用户空间从这里到这里,内核从用户空间的结尾到X”,在这方面使事情变得简单得多。我们可以在某些代码中只需写kernel = 0; if (address > max_userspace) kernel=1;来区分内核和用户空间。

当然,内核只占用实际将使用的物理内存 - 因此普遍认为“占用整个千兆字节的内核是浪费”的想法是错误的 - 内核本身只占用几个(甚至对于非常“大”的内核也只有十几个)兆字节。加载的模块可以轻松地添加更多兆字节,而来自ATI和nVidia的图形驱动程序仅为内核模块本身增加了数兆字节。内核还使用一些内存位来存储“内核数据”,例如任务、队列、信号量、文件和其他内核必须处理的“东西”。同样需要几兆字节的内存。


感谢详细的解释。我明白分页内存映射是实现虚拟内存概念的手段,这种分页内存映射是由x86架构中CR0寄存器中的第31位驱动的。 - Sandeep Arora

8
虚拟内存管理是Linux的一个功能,它使得系统可以进行多任务处理,而且没有对任务数或每个任务使用的内存量的限制。Linux内存管理子系统(以及MMU硬件)实现了虚拟内存管理支持,其中通过虚拟地址访问内存或映射设备。在Linux中,除非涉及真正的硬件,否则所有内容(包括内核和用户组件)都使用虚拟地址。这时候内存管理器就派上用场了,它执行虚拟到物理地址转换,并指向物理内存/设备位置。
进程是由内核定义的抽象实体,为其分配系统资源以执行程序。在Linux进程管理中,内核是进程内存映射的一个集成部分。进程有两个主要区域,就像一枚硬币的两个面:
- 用户空间视图 - 包含进程使用的用户程序部分(代码、数据、堆栈、堆等) - 内核空间视图 - 包含维护关于进程信息的内核数据结构(PID、状态、FD、资源使用等)
在Linux系统中,每个进程都有一个独特且单独的用户空间区域。Linux VMM的这个特性将每个进程的程序部分与其他部分隔离开来。但是,系统中的所有进程共享相同的内核空间区域。当一个进程需要从内核获得服务时,它必须在此区域中执行内核代码,或者换句话说,内核代表用户进程执行请求。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接