2014-01-14 64 views
5

我知道这可能是一个愚蠢的问题,但我一直在寻找一段时间,无法找到明确的答案。如果我使用mmapmalloc(在C中,在一台Linux机器上)是否要在RAM中分配空间?例如,如果我有2GB的RAM,并且想要使用所有可用的RAM,我可以只使用malloc/memset组合,mmap,还是有其他选项我不知道?mmap或malloc分配RAM吗?

我想写一个系列,可以同时运行,并保持在这个过程中用来强制互换使用的所有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

我会建议看看'mlock()'或'mlockall()',因为他们在文档中说他们可以将进程的虚拟地址空间锁定到RAM中。 – Macattack

+0

非常依赖操作系统,但由于操作系统管理的优先级,我不认为RAM会保持使用,如果你加载另一个程序,运行的程序将使用RAM,其他人将去交换 –

+0

这里是一个更长的解释,如果你想更详细地去: http://stackoverflow.com/questions/2688466/why-mallocmemset-is-slower-than-calloc/2688522#2688522 [1]:http://stackoverflow.com/questions/2688466/why-mallocmemset-is-slow-calloc/2688522#2688522 – Alex

回答

9

这是非常OS /机器相关。

在大多数操作系统中都没有分配RAM。他们都分配虚拟机空间。他们使您的进程虚拟内存的一定范围有效使用。内存通常在第一次写入时由OS随后分配。在那之前,这些分配不使用RAM(除了将其列为有效VM空间的页表)。

如果你想分配的物理内存,那么你必须让每一页(sysconf(_SC_PAGESIZE)给你的系统PAGESIZE)肮脏。

在Linux中,你可以看到在/proc/self/smaps所有细节你的虚拟机映射。 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,但(取决于你的系统),实现它可能只是失败mmapENOMEM如果您尝试绘制更多的图像,则可以使用RAM。

+0

smaps中的标题格式是什么?例如,第一行是“00400000-0040b000 r-xp 00000000 fd:00 1048608”我假设前两个是物理内存中的开始/结束地址,如果是,其他的是什么? – cHam

+0

@cHam所有地址都是虚拟机地址。随着时间的推移,你不会在任何地方找到物理地址。 'r-xp'是权限(在这种情况下是读/执行/私有)。零是底层映射文件(如果适用)的偏移量,底层文件/设备映射的设备描述符。最后一个是映射设备的inode,如果不适用,则为0。有关更多详细信息,请参阅http://linux.die.net/man/5/proc。 –

+0

对于如何使每个页面变脏,你有什么建议吗?我不知道我该怎么处理(sysconf(_SC_PAGESIZE))... – cHam

4

理论和实践在这里差别很大。理论上,mmapmalloc都没有分配实际的RAM,但实际上它们都是。

mmap将分配RAM来存储一个虚拟存储区的数据结构(VMA)。如果mmap用于映射实际文件,它将(除非明确告知不同)进一步分配几页RAM以预取映射文件的内容。
除此之外,它只有保留地址空间,并且RAM将在首次访问时分配。

malloc,同样,只有在逻辑上保留你的进程的虚拟地址空间内的地址空间用量或者通过sbrk或者说,它要管理地址的一些(比你要求通常大得多)区mmap告诉操作系统空间。然后通过一些或多或少复杂的算法来细分这个巨大的区域,并最终保留一部分地址空间(正确对齐和舍入)供您使用,并返回一个指向它的指针。
但是:malloc也需要在某处存储一些附加信息,或者free将不可能在稍后时间完成其工作。除了起始地址之外,至少free需要知道分配的块的大小。因此,malloc因此暗中分配一些额外的字节,这些字节紧接在你得到的地址之前 - 你不知道,它不会告诉你。

现在问题的症结是,虽然在理论上malloc不接触它在实践中的管理和不分配物理内存,记忆它。这确实会导致页面错误和内存页面被创建(即正在使用RAM)。
你可以在Linux下通过保持呼叫malloc来验证这一点,并观察OOP杀手爆炸你的过程不存在,因为系统用完物理RAM时,实际上应该是应该剩下很多。