【问题标题】:Is heap allocated on memory pages?堆是在内存页上分配的吗?
【发布时间】:2011-12-30 16:13:47
【问题描述】:

在Linux x86-64环境下,整个进程是分配在虚拟内存页上的吗?整个过程是指文本、数据、bss、堆和堆栈?

另外,当 libc 调用 Brk 时,内核是否返回由虚拟内存管理器通过页面管理的内存?

最后,进程能否在堆上获取内存,这不是由虚拟内存管理器管理的,换句话说,进程能否访问物理内存?

【问题讨论】:

    标签: linux memory


    【解决方案1】:

    In Linux x86-64 environment, is the entire process allocated on virtual memory pages?

    是的,所有进程都有一个虚拟地址空间,即有自己的页表和虚拟内存到物理内存的映射模式。

    Also, when libc calls Brk, does the kernel returns memory that is managed via pages by virtual memory manager ?

    是的,事实上,如果你没有破解操作系统内核,虚拟内存对你来说是透明的。

    can a process get memory on heap, which is not managed by virtual memory manager, in other words, can a process get access to physical memory?

    不,据我所知,除非您在没有操作系统支持的情况下运行程序,否则您无法管理物理内存。因为进程有自己的虚拟空间,所有与内存管理相关的操作都在虚拟内存上。

    【讨论】:

      【解决方案2】:

      一个进程有一个或多个任务(由内核调度),对于多线程进程是进程的线程(对于非线程进程是运行进程的任务),并且它有一个地址空间(以及其他一些资源,例如打开的文件描述符)。

      当然,地址空间是在虚拟内存中。内核允许交换页面(例如磁盘的交换区域)。它尽量避免这样做(将页面交换到磁盘非常慢,因为磁盘访问时间是几十毫秒,而 RAM 访问时间是十分之一微秒)。

      text & bss 等是虚拟内存段,是内存映射。您可以将进程空间视为内存映射。 mmap(2) 系统调用是修改它的方法。当一个可执行文件以execve 系统调用启动时,内核会建立一些映射(例如,文本、数据、bss、堆栈……)。 sbrk(2) 系统调用也会改变它。大多数malloc 实现使用mmap(至少对于足够大的区域),有时使用sbrk

      您可以通过使用 mlock(2) 系统调用将内存范围锁定到 RAM 来避免内存范围被换出,这通常需要 root 权限。它在实践中很少有用(除非您编写实时应用程序)。还有msync 系统调用(将内存刷新到磁盘),您当然可以将文件的一部分映射到虚拟内存(使用mmap),您可以使用mprotect(2) 更改保护,使用@987654327 删除映射@,使用mremap 扩展映射 - 特定于 Linux 的系统调用 -,您甚至可以捕获 SIGSEGV 信号并处理它(通常以特定于机器的方式)。 madvise(2) 系统调用使您能够使用提示调整分页。

      您可以通过阅读/proc/1234/maps 文件(或/proc/1234/smaps)来了解pid 为1234 的进程的内存映射。 (在应用程序内部,您可以使用/proc/self/ 而不是/proc/1234/ ...)我建议您在终端中运行:

      cat /proc/self/maps
      

      它将显示运行cat 命令的进程的内存映射。您还可以使用pmap 实用程序。

      最新的 linux 内核提供Adress Space Layout Randomization(因此在相同输入上运行相同程序的两个相似进程具有不同的mmap-ed 和malloc-ed 地址)。你可以通过/proc/sys/kernel/randomize_va_space禁用它

      【讨论】:

        【解决方案3】:

        除了在极少数情况下(uClinux),进程只能看到虚拟内存,由内核映射到物理内存。

        可以要求内核进行特定的映射,为给定的虚拟地址提供可预测的物理地址;但是,您需要适当的能力来执行此操作,因为这会破坏流程分离。

        execve 上,当前映射被指定的 ELF 文件中的可加载段替换;这些被映射,以便从 ELF 文件加载引用的页面(还执行一些初始预读)。 brk系统调用主要是把最高地址的非可执行映射(不包括栈映射)扩展了几页,让进程可以访问更多的虚拟地址而不用发SIGSEGV

        堆一般由进程内部管理,但分配给堆对象的虚拟地址空间必须事先让虚拟内存管理器知道,才能创建映射。 malloc 通常会在其内部表中查找已映射且可用的区域,如果找不到,请使用 brk()mmap() 创建更多映射。

        【讨论】:

          猜你喜欢
          • 2014-11-02
          • 2017-11-28
          • 1970-01-01
          • 2020-09-02
          • 2021-04-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-10
          相关资源
          最近更新 更多