Articles of 虚拟内存

我想在Linux / C / C ++中使用一个任意大的缓冲区

基本上我想要一个任意大的堆栈。 我知道这是不可能的,但我能为它留出几个TB的虚拟地址空间吗? 我希望能够从头开始,并根据需要走到缓冲区,Linux可以根据需要从物理内存中引入页面。 是这样的可能吗? 它会像malloc缓冲区一样具有相同的性能吗? 有没有办法向Linux发出信号:一旦你popup堆栈,你就完成了内存的设置? 编辑:我想要这个,因为我想优化一个recursion/并行algorithm,在每次调用分配大量的内存。 Malloc对我来说太慢了,我不希望所有的线程在malloc的锁里面互相绊倒。 所以基本上它将是我自己的运行时间堆栈和真正的堆栈(每个线程一个)。 实际上,只要运行时间足够大就足够了。 有没有办法知道/确保堆栈的大小? 在64位地址空间中,有足够的空间让几个线程堆栈分配千兆字节的数据。 那可行吗? 它看起来像pthread_attr_setstacksize可以为新线程工作,但是这并没有什么帮助,如果你可以从任何线程调用…

Linux,将在第一次读取或第一次写入时归零页面错误?

我的问题是Linux特定的,需要了解内核,虚拟内存,mmap,页面错误。 我有C程序与大静态数组,将进入BSS部分(内存,初始化为零)。 程序启动时,这个内存不是物理分配的,只有虚拟内存,虚拟内存的每一页都映射到特殊的零页面(全零页面)。 当应用程序访问此页面时,将生成页面错误并分配物理页面。 问题是:这样的页面错误会在第一次读取访问时生成,还是首先从bss部分写入访问页面?

分配最大的缓冲区而不使用交换

在Linux下的C / C ++中,为了存储来自连接到以太网端口的传感器的实时数据,并以大约110MB / s的速率stream式传输数据,我需要分配一个大的(几个千兆字节)内存块。 我想分配尽可能多的内存,以最大化我可以存储的数据序列的长度。 但是,我还需要确保不会有磁盘交换,因为由此产生的延迟和有限的磁盘访问带宽会导致传感器(非常有限)的缓冲区溢出。 确定要分配多less内存的最佳方法是什么? 我仅限于分配一个比报告的空闲内存稍小的块,或者我可以更直接地与Linux虚拟内存pipe理器接口吗?

Linux Zero-Copy:使用vmsplice在两个进程之间传输内存页面

目前,我正在尝试了解splice / vmsplice的价值。 关于IPC的使用情况,我偶然发现了以下在计算器上的答案: https : //stackoverflow.com/a/1350550/1305501 问题:如何使用vmsplice将内存页从一个进程转移到另一个进程而不复制数据(即零拷贝)? 上面提到的答案声称这是可能的。 但是,它不包含任何源代码。 如果我正确理解了vmsplice的文档,下面的函数将把内存页面传送到一个pipe道(内核缓冲区)而不复制,如果内存被正确分配和alignment的话。 error handling省略,以便于演示。 // data is aligned to page boundaries, // and length is a multiple of the page size void transfer_to_pipe(int pipe_out, char* data, size_t length) { size_t offset = 0; while (offset < length) { struct iovec iov { data + offset, length […]

在进程内分配写入内存上的副本

我有一个内存段,这是通过mmap与MAP_ANONYMOUS获得的。 我怎样才能分配第二个相同大小的引用第一个内存段,并在Linux(目前在工作Linux 2.6.36)进行拷贝写入? 我想和fork有完全相同的效果,只是没有创build一个新的进程。 我希望新的映射保持在同一个过程中。 整个过程必须在原始和复制页面上重复(就像父母和孩子将继续fork )。 我不想分配整个段的直接副本的原因是因为它们是多个千兆字节大,我不想使用可能是写入时复制共享的内存。 我曾经尝试过: mmap段共享,匿名。 在复制mprotect它为只读,并创build与remap_file_pages也是只读的第二个映射。 然后使用libsigsegv拦截写入尝试,手动创build页面的副本,然后mprotect都读写。 诀窍,但是很肮脏。 我基本上实现了我自己的虚拟机。 不幸的是, mmap ing /proc/self/mem在当前的Linux上不受支持,否则MAP_PRIVATE映射就可以实现。 写入拷贝机制是Linux VM的一部分,必须有一种方法可以在不创build新进程的情况下使用它们。 作为一个说明:我已经find了马赫VM的适当机制。 下面的代码在我的OS X 10.7.5上编译,并具有预期的行为: Darwin 11.4.2 Darwin Kernel Version 11.4.2: Thu Aug 23 16:25:48 PDT 2012; root:xnu-1699.32.7~1/RELEASE_X86_64 x86_64 i386 Darwin 11.4.2 Darwin Kernel Version 11.4.2: Thu Aug 23 16:25:48 PDT 2012; root:xnu-1699.32.7~1/RELEASE_X86_64 x86_64 i386 gcc […]

Linux(Ubuntu),C语言:虚拟到物理地址转换

正如标题所示,我有一个从虚拟地址获取物理地址的问题。 让我来解释一下:在进程空间中给定一个variables声明,我怎样才能得到它由OS映射的物理地址? 我偶然发现了一些调用virt_to_phys()函数的sys调用/asm/io.h ; 不过看起来这个标题已经过时了,我找不到工作。 然而; io.h可在以下位置获得: /usr/src/linux-headers-2.6.35-28-generic/arch/x86/include/asm/ 。 我当前的内核是2.6.35-28 ,但是io.h不包含在/usr/include/asm/ ? 所以,重申:我需要一种方法来从虚拟获得物理地址。 优选地在运行时从应用程序内导出。 但即使是使用/proc/PID/maps监视器的解决方法也可以。 任何想法或意见将不胜感激。 编辑在做了一些关于这个话题的研究之后,我发现了一些在这方面有所帮助的东西。 事实certificate这是可行的,虽然需要一些解决方法。 这是一个简单的应用程序分析当前映射页面的链接。 有问题的文件结果是(二进制文件) /proc/pid/pagemap (包含虚拟页面的物理映射)。 无论如何,该链接中的代码可以修改为监视器应用程序或其他东西。 我需要物理地址来进行caching模拟。 感谢所有的帮助和解答!

Linux 3/1虚拟地址分割

当我们想要理解highmem解决超过1GB内存的需求时,我错过了一些东西。 有人能指出我出错的地方吗? 谢谢! 我知道的: 1 GB进程的虚拟内存(高内存区域)被保留用于内核操作。 用户空间可以使用剩余的3 GB。 这是3/1分裂。 VM的虚拟内存function将(连续)虚拟内存页面映射到物理页面(RAM)。 我不知道的是: 什么操作使用内核虚拟内存? 我猜想内核空间中的kmalloc(…)会使用内核虚拟内存。 我认为在这个scheme下可以使用4GB的RAM。 我不明白为什么内核1GB虚拟空间是寻址物理空间的限制因素。 这是我理解失败的地方。 请指教。 我一直在阅读这个( http://kerneltrap.org/node/2450 ),这很棒。 但是这并不能解决我的问题。

64位大型mallocs

malloc()会失败的原因是什么,特别是在64位? 我的具体问题是在64位系统上尝试malloc一个巨大的10GB块。 该机器有12GB的RAM和32GB的交换。 是的,malloc是极端的,但为什么会是一个问题呢? 这是在Windows XP64与英特尔和MSFT编译器。 malloc有时成功,有时不成功,约50%。 8GB malloc总是工作,20GB malloc总是失败。 如果一个malloc失败了,重复的请求将不会起作用,除非我退出这个进程并重新开始一个新的进程(然后成功的时候会有50%的成功)。 没有其他大应用程序正在运行。 即使在重新启动后也会立即发生。 我可以想象一个malloc在32位失败,如果你已经使用了32位(或31位)的可用地址空间,那么没有足够大的地址范围来分配你的请求。 我也可以想象,如果你用完了你的物理RAM 和你的硬盘交换空间,malloc会失败。 这不是我的情况。 但是为什么malloc可能会失败呢? 我想不出其他的原因。 我对通用malloc问题比我的具体例子更感兴趣,我可能会用内存映射文件replace它。 失败的malloc()只不过是一个比其他任何东西都更让人困惑的东西……那种渴望理解你的工具而不会被基础知识所惊讶的东西。

意外的页面处理(另外,VirtualLock = no op?)

今天早上,我偶然发现了一个我没想到会发生的令人惊讶的页面错误。 是的,我可能不应该担心,但它仍然令我感到奇怪,因为根据我的理解,它们不应该发生。 而且,如果他们没有,我会更好。 该应用程序(在WinXP Pro 32位下)使用VirtualAlloc(MEM_RESERVE) )保留更大的地址空间(1GB),稍后使用VirtualAlloc(MEM_RESERVE)分配适当大的内存块VirtualAlloc(MEM_COMMIT) 。 这是在工作人员提前完成的,意图是尽可能less地拖动主线。 显然,除非内存区域当前被locking,否则不能确保没有页面错误发生,但其中的一些肯定是可以忍受的(并且是不可避免的)。 令人惊讶的是每一个页面都有错误。 总是。 因此,假定系统只是在分配它们之后懒洋洋地创build页面,这在某种程度上也是有意义的(尽pipe文档提供了不同的东西)。 够公平的,我的不好。 因此,显而易见的解决方法是VirtualLock / VirtualUnlock ,它强制系统创build这些页面,因为它们必须在VirtualLock返回后存在。 令人惊讶的是, 仍然每一个页面错误 。 于是我写了一个小testing程序,按顺序完成了上面所有的步骤,每个程序间rest5秒钟,以排除其他代码中的错误。 结果是: MEM_RESERVE 1GB —>成功,零CPU,零时间,没有任何反应 MEM_COMMIT 1 GB —>成功,零CPU,零时间,工作集增加2MB,512页错误(分别在用户空间每页分配8个字节的元数据) for(… += 128kB) { VirtualLock(128kB); VirtualUnlock(128kB); } 成功,零CPU,零时间,没有任何反应 for(… += 4096) *addr = 0; —> 262144页面错误,约0.25秒(内核时间〜95%)。 Process Explorer中的“工作集”和“物理”都增加了1GB VirtualFree —>零CPU,零时间,无论是“工作集”还是“物理”,瞬间都会变成* poof *。 我的期望是,由于每一页都被locking了一次,所以至less在这之后它必须物理存在。 当超过配额时,它当然仍然可以被移入和移出WS(只要有足够的RAM可用,就改变一个参考)。 然而,执行时间,工作集和物理内存度量都不支持这一点。 […]

Windows – 提交大小与虚拟大小

我想知道提交大小 (在任务pipe理器中可见)和虚拟大小 (在SysInternals的Process Explorer中可见)之间的确切区别。 Process Explorer中的 “ 虚拟大小”参数看起来像一个stream程的总体虚拟内存使用情况的更准确的指标。 但是提交大小始终小于虚拟大小 ,我想它不包括进程正在使用的所有虚拟内存。 我希望有人解释这些参数中包含的内容。