我想编写一个程序来消耗所有可用的内存来理解结果。我听说linux一旦无法分配内存就开始杀死进程。
任何人都可以帮我解决这个问题。
我写了以下内容,但内存似乎没有用尽:
#include <stdlib.h>
int main()
{
while(1)
{
malloc(1024*1024);
}
return 0;
}
答案 0 :(得分:13)
您应该写入已分配的块。如果你只是要求内存,linux可能只是分发内存预留,但在访问内存之前不会分配任何内容。
int main()
{
while(1)
{
void *m = malloc(1024*1024);
memset(m,0,1024*1024);
}
return 0;
}
你真的只需要在每个页面上写1个字节(通常在x86上为4096个字节)。
答案 1 :(得分:10)
Linux“over commit”内存。这意味着物理内存仅在进程首次尝试访问时为进程提供,不时首次执行malloc
。要禁用此行为,请执行以下操作(以root用户身份):
echo 2 > /proc/sys/vm/overcommit_memory
然后尝试运行您的程序。
答案 2 :(得分:3)
默认情况下,Linux使用我称之为“机会分配”的东西。这是基于观察到许多真实程序分配的内存比实际使用的内存多。 Linux使用它来将更多内容放入内存:它只在使用时分配一个内存页面,而不是在使用malloc(或mmap或sbrk)分配时。
如果你在循环中做了类似的事情,你可能会取得更大的成功:
memset(malloc(1024*1024L), 'w', 1024*1024L);
答案 3 :(得分:3)
一个鲜为人知的事实(尽管已有详细记录) - 您可以(以root身份)阻止OOM杀手将您的流程(或任何其他流程)声称为其受害者之一。这是一个直接来自我的编辑器的片段,我(基于配置数据)锁定所有已分配的内存以避免被分页和(可选)告诉OOM杀手不要打扰我:
static int set_priority(nex_payload_t *p)
{
struct sched_param sched;
int maxpri, minpri;
FILE *fp;
int no_oom = -17;
if (p->cfg.lock_memory)
mlockall(MCL_CURRENT | MCL_FUTURE);
if (p->cfg.prevent_oom) {
fp = fopen("/proc/self/oom_adj", "w");
if (fp) {
/* Don't OOM me, Bro! */
fprintf(fp, "%d", no_oom);
fclose(fp);
}
}
我没有显示我正在使用调度程序参数做什么,因为它与问题无关。
这将阻止OOM杀手在它有机会产生(在这种情况下)所需效果之前获得你的过程。实际上,您还会将大多数其他进程强制转移到磁盘上。
所以,简而言之,要快速看烟花......
请务必同时查看ulimit
,并以root身份运行测试。
我展示的代码是守护进程的一部分,它不会失败,它以非常高的权重运行(有选择地使用RR或FIFO调度程序)并且不能(永远)被分页。
答案 4 :(得分:3)
在我的机器中,使用适当的gb
值,以下代码使用了100%的内存,甚至将内存放入交换中。
您可以看到每个页面只需要写一个字节:memset(m, 0, 1);
,
如果您将页面大小:#define PAGE_SZ (1<<12)
更改为更大的页面大小:#define PAGE_SZ (1<<13)
,那么您将不会写入您分配的所有页面,因此您可以在顶部看到程序的内存消耗沮丧。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PAGE_SZ (1<<12)
int main() {
int i;
int gb = 2; // memory to consume in GB
for (i = 0; i < ((unsigned long)gb<<30)/PAGE_SZ ; ++i) {
void *m = malloc(PAGE_SZ);
if (!m)
break;
memset(m, 0, 1);
}
printf("allocated %lu MB\n", ((unsigned long)i*PAGE_SZ)>>20);
getchar();
return 0;
}
答案 5 :(得分:2)
看一下这个程序。 当没有足够的内存时,malloc开始返回0
#include <stdlib.h>
#include <stdio.h>
int main()
{
while(1)
{
printf("malloc %d\n", (int)malloc(1024*1024));
}
return 0;
}
答案 6 :(得分:1)
在32位Linux系统上,单个进程在其地址空间中可以分配的最大值大约为3Gb。
这意味着你不可能只用一个进程耗尽内存。
另一方面,在64位计算机上,您可以根据需要进行分配。
正如其他人所说,还需要初始化内存,否则它实际上不会占用页面。
如果操作系统没有剩余虚拟内存,或者进程超出地址空间(或者不足以满足请求的分配),则malloc将开始发出错误。
正如其他人所指出的那样,Linux的虚拟机过度使用也会影响它的确切时间和发生的情况。答案 7 :(得分:0)
我曾厌倦过这样做过。得到这个耗尽所有内存,需要强制重新启动才能让它再次运行。
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char** argv)
{
while(1)
{
malloc(1024 * 4);
fork();
}
}
答案 8 :(得分:0)
如果您只需要强调系统,那么就会有stress工具,它可以完全满足您的需求。它可以作为大多数发行版的包装。
答案 9 :(得分:-1)
我刚刚执行了@John La Rooy的片段:
#include <stdlib.h> #include <stdio.h> int main() { while(1) { printf("malloc %d\n", (int)malloc(1024*1024)); } return 0; }
但它很快耗尽了我的记忆并导致系统被绞死,所以我不得不重新启动它。
所以我建议你改变一些代码。
例如: 在我的ubuntu 16.04 LTS上,下面的代码大约需要1.5 GB ram,执行后物理内存消耗从1.8 GB增加到3.3 GB,并在完成执行后回落到1.8GiB。虽然看起来我在代码中分配了300GiB ram。
#include <stdlib.h>
#include <stdio.h>
int main()
{
while(int i<300000)
{
printf("malloc %p\n", malloc(1024*1024));
i += 1;
}
return 0;
}
当索引 i 小于100000(即分配小于100 GB)时,物理或虚拟内存只是略微使用(小于100MB),我不知道为什么,可能与虚拟内存有关。
有趣的是,当物理内存开始缩小时,地址malloc()肯定会返回更改,请参阅下面的图片链接。
我使用了malloc()和calloc(),似乎它们在占用物理内存方面表现得相似。
memory address number changes from 48 bits to 28 bits when physical memory begins shrinking