我知道这可能是一个愚蠢的问题,但我一直在寻找一段时间,但无法找到明确的答案。如果我使用mmap
或malloc
(在C中,在Linux机器上),是否在RAM中分配空间?例如,如果我有2GB的RAM并希望使用所有可用的RAM,我可以使用malloc/memset
组合,mmap
,还是有其他我不知道的选项?
我想编写一系列可以同时运行的简单程序,并保留进程中使用的所有RAM以强制使用交换,并且频繁地交换页面。我已经尝试过以下程序,但这并不是我想要的。它确实分配了内存(RAM?),并强制使用交换(如果有足够的实例正在运行),但是当我调用sleep
时不会只是锁定内存被使用(所以实际上什么都没有被交换)进出其他进程?),或者我误解了什么。
例如,如果我运行了3次,那么我将使用前两个实例中的2GB(全部)RAM,然后第三个实例会将前两个实例之一(RAM)和当前实例交换掉进入RAM?或者实例#3是否只使用磁盘或虚拟内存运行?
这提出了另一点,我是否需要分配足够的内存来使用所有可用的虚拟内存以及要使用的交换分区?
最后,mmap
(或任何其他C函数。地狱,甚至是另一种语言,如果适用)会更好吗?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MB(size) ( (size) * 1024 * 1024)
#define GB(size) ( (size) * 1024 * 1024 * 1024)
int main(){
char *p;
p = (char *)malloc(MB(512));
memset(p, 'T', MB(512));
printf(".5 GB allocated...\n");
char *q;
q = (char *)malloc(MB(512));
memset(q, 'T', MB(512));
printf("1 GB allocated...\n");
printf("Sleeping...\n");
sleep(300);
}
**编辑:我正在为我的操作系统使用CentOS 6.4(带有3.6.0内核),如果这有帮助的话。
答案 0 :(得分:13)
这是非常依赖OS /机器的。
在大多数操作系统中,都不分配RAM。它们都分配VM空间。它们使您的进程虚拟内存的某个范围有效使用。 RAM通常在第一次写入时由OS稍后分配。在那之前,这些分配不使用RAM(除了将它们列为有效VM空间的页表之外)。
如果要分配物理RAM,则必须使每个页面(sysconf(_SC_PAGESIZE)
为您提供系统页面大小)脏。
在Linux中,您可以在/proc/self/smaps
中看到包含所有详细信息的VM映射。 Rss
是你映射的常驻集合(驻留在RAM中多少),其他所有脏的都将被换出。所有非脏内存都可以使用,但在此之前不会存在。
你可以用
之类的东西弄脏所有页面size_t mem_length;
char (*my_memory)[sysconf(_SC_PAGESIZE)] = mmap(
NULL
, mem_length
, PROT_READ | PROT_WRITE
, MAP_PRIVATE | MAP_ANONYMOUS
, -1
, 0
);
int i;
for (i = 0; i * sizeof(*my_memory) < mem_length; i++) {
my_memory[i][0] = 1;
}
在某些实现方面,这也可以通过将MAP_POPULATE
标记传递给mmap
来实现,但是(取决于您的系统)如果mmap
ENOMEM
可能会失败,如果你尝试映射更多,然后你有RAM可用。
答案 1 :(得分:6)
理论和实践在这里有很大不同。从理论上讲,mmap
和malloc
都不会分配实际的RAM,但实际上它们会分配。
mmap
将分配RAM以存储虚拟内存区域数据结构(VMA)。如果mmap
与要映射的实际文件一起使用,它将(除非明确说明不同)进一步分配几页RAM以预取映射文件的内容。
除此之外,只有保留地址空间,RAM将在第一次访问时分配。
malloc
仅通过sbrk
或mmap
告知操作系统管理某些操作系统,从而在逻辑上保留流程虚拟地址空间内的地址空间量(通常比你要求的要大得多)地址空间区域。然后通过一些或多或少复杂的算法细分这个巨大的区域,最后保留一部分地址空间(正确对齐和圆形)供您使用,并返回指向它的指针。
但是: malloc
还需要在某处存储一些其他信息,否则free
将无法在以后执行其工作。除了起始地址之外,至少free
需要知道已分配块的大小。通常,malloc
因此秘密地分配了一些额外的字节,这些字节紧跟在你得到的地址之前 - 你不知道,它没有告诉你。
现在问题的关键在于,理论上 malloc
不会触及它管理的内存并且不会分配物理RAM,在实践中它> EM>。这确实会导致页面错误和内存页面被创建(即正在使用的RAM)
您可以在Linux下通过调用malloc
验证这一点,并观察OOP杀手爆炸您的进程是否已经存在,因为系统耗尽了物理RAM,而实际上应该剩余。