[英]Can I create an array exceeding RAM, if I have enough swap memory?
假设我有 8 GB 的 RAM 和 16 GB 的交换空间 memory。我可以在 C 中分配一个 20 GB 的数组吗? 如果是,那怎么可能? memory 布局会是什么样子?
[linux] 如果我有足够的交换空间 memory,我可以创建一个超过 RAM 的数组吗?
是的你可以。 请注意,访问 swap 非常慢。
这怎么可能
分配动态 memory。操作系统处理 rest。
memory 布局会是什么样子?
在 amd64 系统上,您可以拥有 256 TiB 的地址空间。 您可以轻松地在该空间中放置一个 8 GiB 的连续块。 操作系统将虚拟 memory 分成页面,并根据需要在物理 memory 和交换空间之间复制页面。
现代操作系统使用虚拟 memory。在 Linux 和大多数其他操作系统中,根据体系结构的能力,rach 进程拥有自己的地址空间。 您可以在/proc/cpuinfo
中检查虚拟地址空间的大小。 例如,您可能会看到:
address sizes : 43 bits physical, 48 bits virtual
这意味着虚拟地址使用 48 位。 其中一半保留给 kernel,因此您只能使用 47 位或 128TiB。 您分配的任何 memory 都将放置在这 128 TiB 地址空间的某个位置,就好像您实际上有那么多 memory 一样。
Linux 使用需求页面加载和默认超过提交 memory。当你说
char *mem = (char*)malloc(1'000'000'000'000);
发生的情况是 Linux 选择了一个合适的地址,并仅记录您从该点开始分配了 memory 的 1'000'000'000'000(四舍五入到最近的页面)。 (它会根据可用的物理 memory 的数量、可用的交换数量和过度使用设置进行一些健全性检查,以确定该数量是否完全疯狂。默认情况下,您可以分配比 memory 多得多的数量,并且交换。)
请注意,此时没有物理 memory 也没有交换空间连接到您分配的块。 当您第一次写入 memory 时,这会发生变化:
mem[4096] = 0;
此时程序会出现page fault。 Linux 检查地址实际上是您的程序被允许写入的地址,找到一个物理页面并将其 map 到&mem[4096]
。 然后它让程序重试在那里写入,一切继续。
如果 Linux 找不到物理页面,它将尝试换出一些东西以使物理页面可用于您的程序。 如果这也失败了,您的程序将收到 SIGSEGV 并可能终止。
因此,只要您从不写入超过物理 memory 和交换和支持的内容,您基本上可以分配无限数量的 memory。 另一方面,如果您初始化 memory(显式或隐式使用calloc()
),系统将很快注意到您是否尝试使用超过可用量。
您可以,但不能使用简单的malloc
。 它依赖于平台。
它需要操作系统调用来分配可交换的 memory(它是 Windows 上的VirtualAlloc
,例如,在 Linux 上它应该是mmap
和相关函数)。 完成后,分配的 memory 被分成pages ,固定大小的连续块。 您可以锁定页面,因此它将加载到 RAM 中,您可以自由读取和修改它。 对于像我这样的老恐龙,这正是 EMS memory 在 DOS 下的工作方式......你用一种segment:offset
方法解决你的可交换 memory:首先,你将你的线性地址除以页面大小以找到需要哪个页面,然后您使用余数来获取此页面内的偏移量。
一旦解锁,该页面将保留在 memory 中,直到操作系统需要 memory:然后,解锁的页面将刷新到磁盘,在交换中,并丢弃在 RAM 中……直到您再次锁定(并加载……)它,但是这操作可能需要释放 RAM,因此在您自己的页面再次加载之前,另一个进程可能会交换其未锁定的页面。 这真是太慢了……即使是在 SSD 上!
因此,使用交换并不总是一件好事。 更好的方法是使用 memory 映射文件——非常适合读取非常大的文件,大部分是顺序读取,很少有随机访问——如果它能满足您的需要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.