在Linux x86-64环境中,整个进程是在虚拟内存页面上分配的吗?整个过程我的意思是文本,数据,bss,堆和堆栈?
此外,当libc调用Brk时,内核是否返回由虚拟内存管理器通过页面管理的内存?
最后,进程是否可以在堆上获取内存,而不是由虚拟内存管理器管理,换句话说,进程是否可以访问物理内存?
答案 0 :(得分: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?
不,除非您在没有操作系统支持的情况下运行程序,否则您无法根据我的知识管理物理内存。因为进程有自己的虚拟空间,所以与内存管理相关的所有操作都在虚拟内存上。
答案 1 :(得分:2)
一个进程有一个或多个任务(由内核调度),对于多线程进程来说,这是一个进程'线程(对于运行该进程的任务的非线程进程),它有一个地址空间(以及一些其他资源,例如打开的文件描述符)。
当然,地址空间在虚拟内存中。允许内核交换页面(例如磁盘的交换区域)。它努力避免这样做(将页面交换到磁盘非常慢,因为磁盘访问时间是几十毫秒,而RAM访问时间是十分之一秒)。
text & bss 等是虚拟内存段,它们是内存映射。您可以将进程空间视为内存映射。 mmap(2)系统调用是修改它的方法。当使用execve系统调用启动可执行文件时,内核会建立一些映射(例如,文本,数据,bss,堆栈......)。 sbrk(2)系统调用也会更改它。大多数malloc
实施都使用mmap
(至少对于足够大的区域),有时使用sbrk
。
通过使用mlock(2)系统调用(通常需要root权限)将内存范围锁定到RAM中,可以避免将内存范围换出。它在实践中很少有用(除非您编写实时应用程序代码)。还有msync系统调用(将内存刷新到磁盘),您当然可以将文件的一部分映射到虚拟内存(使用mmap
),您可以使用mprotect(2)更改保护,使用munmap(2)删除地图,使用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
答案 2 :(得分:1)
除了非常罕见的情况(uClinux)之外,进程只能看到内核映射到物理内存的虚拟内存。
可以要求内核进行特定的映射,为给定的虚拟地址提供可预测的物理地址;然而,你需要适当的能力才能做到这一点,因为这会破坏过程分离。
在execve
上,当前映射被指定的ELF文件中的可加载段替换;这些被映射,以便从ELF文件加载引用的页面(也执行一些初始的readahead)。 brk
系统调用主要将具有最高地址(不包括堆栈映射)的非可执行映射扩展几页,从而允许进程访问更多虚拟地址而不发送SIGSEGV
。
堆通常由内部进程管理,但事先必须为虚拟内存管理器分配分配给堆对象的虚拟地址空间才能创建映射。 malloc
通常会查看已映射和可用的区域的内部表,如果找不到,请使用brk()
或mmap()
创建更多映射。