2011-12-30 48 views
1

在Linux x86-64环境中,整个进程是在虚拟内存页面上分配的吗?整个过程我的意思是文本,数据,BSS,堆和堆栈?在内存页面上分配了堆吗?

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

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

回答

3

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?

不,你不能,除非你不从OS支持运行您的程序管理按我的知识的物理内存。由于进程有其自己的虚拟空间,因此与内存管理相关的所有操作都在虚拟内存上。

2

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

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

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

使用系统调用mlock(2)系统调用(通常需要root权限),可以避免将内存范围锁定到RAM中,从而取消内存范围。在实践中很少有用(除非您编写实时应用程序)。系统调用还有msync系统调用(将内存刷新到磁盘),你当然可以将一部分文件映射到虚拟内存中(使用mmap),可以用mprotect(2)更改保护,用munmap(2)更改保护,用mremap扩展映射 - 一个特定于Linux的系统调用 - ,你甚至可以捕获信号并处理它(通常是以一种特定于计算机的方式)。使用系统调用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

1

除非常罕见的情况下(uClinux),进程只看到虚拟内存,由内核映射到物理内存。

可以要求内核制定给定虚拟地址的可预测物理地址的特定映射;然而,您需要适当的能力才能做到这一点,因为这会打破流程分离。

execve上,当前映射由指定的ELF文件中的可加载段替换;这些映射使得从ELF文件加载引用的页面(也执行一些初始预读)。系统调用主要将具有最高地址(不包括堆栈映射)的不可执行映射扩展几页,允许进程访问更多虚拟地址,而不会发送SIGSEGV

堆一般由进程在内部进行管理,但为了创建映射,虚拟内存管理器必须事先知道分配给堆对象的虚拟地址空间。 malloc通常会查看其已经映射和可用的区域的内部表格,如果找不到任何区域,则使用brk()mmap()来创建更多映射。