Vik*_*kas 44 c malloc operating-system memory-management computer-architecture
我试图在我的机器(1 Gb RAM 160 Gb HD Windows平台)上计算出最大程度上可以使用多少内存.
我读到malloc可以分配的最大内存仅限于物理内存(堆上).
此外,当程序超过内存消耗到某个级别时,计算机将停止工作,因为其他应用程序无法获得所需的足够内存.
所以要确认一下,我在C写了一个小程序:
int main(){
int *p;
while(1){
p=(int *)malloc(4);
if(!p)break;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望有一段时间内存分配失败并且循环会中断,但是我的计算机挂起,因为它是一个无限循环.
我等了大约一个小时,最后我不得不强行关闭电脑.
一些问题:
Ale*_*lli 47
我读到最大内存
malloc
可以分配的内存仅限于物理内存(堆上).
错误:大多数计算机/操作系统支持虚拟内存,由磁盘空间支持.
一些问题:是否
malloc
也从HDD分配内存?
malloc
询问操作系统,反过来可能会使用一些磁盘空间.
上述行为的原因是什么?为什么循环在任何时候都没有中断?
为什么没有分配失败?
你刚才要求的次数太少:最终循环会中断(在你的机器由于虚拟物理内存和物理内存的大量过剩而导致爬行速度变慢,以及随之而来的超级频繁磁盘访问,这个问题被称为"颠簸" ")但在此之前它已经耗尽了你的耐心.尝试一次获得例如一兆字节.
当程序超过内存消耗到某个级别时,计算机将停止工作,因为其他应用程序无法获得足够的内存.
总停止不太可能,但是当通常需要几微秒的操作最终花费(例如)几十毫秒时,这四个数量级当然可以使感觉好像计算机基本停止了,通常需要什么一分钟可能需要一个星期.
Seb*_*ian 25
我知道这个帖子已经老了,但是对于任何愿意自己试一试的人来说,请使用此代码剪断
#include <stdlib.h>
int main() {
int *p;
while(1) {
int inc=1024*1024*sizeof(char);
p=(int*) calloc(1,inc);
if(!p) break;
}
}
Run Code Online (Sandbox Code Playgroud)
跑
$ gcc memtest.c
$ ./a.out
Run Code Online (Sandbox Code Playgroud)
在运行时,此代码填充RAM,直到被内核杀死.使用calloc而不是malloc来防止"懒惰评估".从这个线程中获取的想法: Malloc Memory Questions
这段代码迅速填满了我的RAM(4Gb),然后在大约2分钟内我的20Gb交换分区才死亡.当然是64位Linux.
/proc/sys/vm/overcommit_memory
控制 Linux 上的最大值
例如,在 Ubuntu 19.04 上,我们可以很容易地看到它malloc
是mmap(MAP_ANONYMOUS
通过使用strace
.
然后man proc
描述如何/proc/sys/vm/overcommit_memory
控制最大分配:
该文件包含内核虚拟内存记帐模式。值是:
- 0:启发式过量使用(这是默认设置)
- 1:总是过量使用,从不检查
- 2:始终检查,永远不要过度使用
模式0下,不检查带有MAP_NORESERVE的mmap(2)调用,默认检查很弱,导致进程“OOM-killed”的风险。
在模式 1 中,内核假装总是有足够的内存,直到内存实际用完为止。这种模式的一个用例是科学计算应用程序?使用大型稀疏数组。在 2.6.0 之前的 Linux 内核版本中,任何非零值都意味着模式 1。
在模式 2(自 Linux 2.6 起可用)中,可以分配的总虚拟地址空间(/proc/meminfo 中的 CommitLimit)计算为
Run Code Online (Sandbox Code Playgroud)CommitLimit = (total_RAM - total_huge_TLB) * overcommit_ratio / 100 + total_swap
在哪里:
- total_RAM 是系统上的 RAM 总量;
- total_huge_TLB 是为大页面预留的内存量;
- overcommit_ratio 是 /proc/sys/vm/overcommit_ratio 中的值;和
- total_swap 是交换空间量。
例如,在具有 16GB 物理 RAM、16GB 交换空间、没有专用于大页面的空间以及 overcommit_ratio 为 50 的系统上,此公式生成 Com? mitLimit 为 24GB。
从 Linux 3.14 开始,如果 /proc/sys/vm/overcommit_kbytes 中的值非零,则 CommitLimit 计算如下:
Run Code Online (Sandbox Code Playgroud)CommitLimit = overcommit_kbytes + total_swap
另请参阅 /proc/sys/vm/admin_reserve_kbytes 和 /proc/sys/vm/user_reserve_kbytes 的说明。
5.2.1 内核树中的Documentation/vm/overcommit-accounting.rst也提供了一些信息,虽然有点少:
Linux 内核支持以下过载处理模式
0
启发式过量使用处理。明显的地址空间过度使用被拒绝。用于典型系统。它确保严重的疯狂分配失败,同时允许过度使用以减少交换使用。在这种模式下允许 root 分配更多的内存。这是默认设置。
1
总是过度使用。适用于某些科学应用。经典示例是使用稀疏数组的代码,并且仅依赖几乎完全由零页组成的虚拟内存。
2
不要过度使用。系统的总地址空间提交不得超过交换区 + 可配置的物理 RAM 量(默认为 50%)。根据您使用的数量,在大多数情况下,这意味着进程在访问页面时不会被终止,但会在适当的内存分配中收到错误。对于希望保证其内存分配在未来可用而无需初始化每个页面的应用程序很有用。
最小的实验
我们可以很容易地看到允许的最大值:
主文件
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
char *chars;
size_t nbytes;
/* Decide how many ints to allocate. */
if (argc < 2) {
nbytes = 2;
} else {
nbytes = strtoull(argv[1], NULL, 0);
}
/* Allocate the bytes. */
chars = mmap(
NULL,
nbytes,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS,
-1,
0
);
/* This can happen for example if we ask for too much memory. */
if (chars == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
/* Free the allocated memory. */
munmap(chars, nbytes);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
编译运行分配1GiB和1TiB:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out 0x40000000
./main.out 0x10000000000
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用分配值来查看系统允许的内容。
我找不到0
(默认)的精确文档,但在我的 32GiB RAM 机器上它不允许 1TiB 分配:
mmap: Cannot allocate memory
Run Code Online (Sandbox Code Playgroud)
但是,如果我启用无限制的过量使用:
echo 1 | sudo tee /proc/sys/vm/overcommit_memory
Run Code Online (Sandbox Code Playgroud)
那么 1TiB 分配工作正常。
模式2
有据可查,但我懒得进行精确计算来验证它。但我只想指出,在实践中,我们可以分配以下内容:
overcommit_ratio / 100
Run Code Online (Sandbox Code Playgroud)
总RAM,并且overcommit_ratio
是50
默认的,所以我们可以对分配内存总量的一半。
VSZ 与 RSS 以及内存不足的杀手
到目前为止,我们刚刚分配了虚拟内存。
然而,在某些时候,如果您使用足够多的这些页面,Linux 将不得不开始杀死一些进程。
我已经详细说明了:什么是 Linux 内存管理中的 RSS 和 VSZ
试试这个
#include <stdlib.h>
#include <stdio.h>
main() {
int Mb = 0;
while (malloc(1<<20)) ++Mb;
printf("Allocated %d Mb total\n", Mb);
}
Run Code Online (Sandbox Code Playgroud)
包括stdlib和stdio.
该提取物取自深层秘密.
归档时间: |
|
查看次数: |
77965 次 |
最近记录: |