繁体   English   中英

如果我有足够的交换空间 memory,我可以创建一个超过 RAM 的数组吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM