Articles of 虚拟内存

传统的gcc编译器问题

我们正在使用一个基于gcc 2.6.0的遗留编译器来交叉编译我们现在仍在使用的旧embedded式处理器(是的,它自1994年起仍在使用!)。 为这个芯片做了gcc端口的工程师早就开始工作了。 尽pipe我们可以从网上的某个地方恢复gcc 2.6.0源码,但是这个芯片的设置已经在公司历史的大厅里消失了。 直到最近,由于编译器仍在运行并生成可用的可执行文件,所以直到最近,我们一直在困惑,但是从2.6.25内核(也是2.6.26)开始,它会失败并显示消息gcc: virtual memory exhausted …即使不带参数运行或只有-v 。 我已经使用2.6.24内核重启了我的开发系统(从2.6.26开始),编译器再次运行(2.6.25不重启)。 我们有一个系统,我们在2.6.24中只是为了构build这个芯片而做的,但是当linux世界移动到我们不能再重build一个将运行的系统编译器(即我们的2.6.24系统死机,我们不能得到2.6.24安装和运行在一个新的系统,因为一些软件部分不再可用)。 有没有人有任何想法,我们可以做一个更现代化的安装,让这个遗留的编译器运行? 编辑 : 回答一些评论… 不幸的是,这是我们的芯片特有的源代码更改丢失。 这个损失发生在两个主要的公司reorgs和几个系统pipe理员(其中几个真的留下了一个烂摊子)。 我们现在使用configuration控制,但是对于这个问题,closures仓库门太晚了。 虚拟机的使用是一个好主意,也可能是我们最终做的事情。 谢谢你的想法。 最后,我试着用ephemientbuild议strace,发现最后一个系统调用是brk(),它在新系统(2.6.26内核)上返回一个错误,并在旧系统(2.6.24内核)上返回成功。 这表明我真的用完了虚拟内存,除了tcsh“limit”在旧系统和新系统上返回相同的值,而/ proc / meminfo显示新系统的内存稍微多一些,交换空间也多了一点。 也许这是一个碎片问题或程序正在加载? 我做了一些进一步的研究,并在内核2.6.25中添加了“brk随机化”,但CONFIG_COMPAT_BRK默认启用(禁用brk随机化)。 编辑 : OK,更多信息:看起来像brk随机化是罪魁祸首,遗留gcc调用brk()来更改数据段的结尾,现在失败,导致遗留gcc报告“虚拟内存已耗尽”。 有几个logging的方法来禁用brk随机化: sudo echo 0 > /proc/sys/kernel/randomize_va_space sudo sysctl -w kernel.randomize_va_space=0 用setarch i386 -R tcsh (或“-R -L”)启动一个新的shell 我已经尝试过,他们似乎有一个效果,brk()返回值是不同的(总是相同的)比没有他们(在内核2.6.25和2.6.26尝试),但brk()仍然失败,所以传统的gcc仍然失败:-(。 另外,我已经设置vm.legacy_va_layout=1和vm.overcommit_memory=2没有任何变化,我已经用/etc/sysctl.conf中保存的vm.legacy_va_layout=1和kernel.randomize_va_space=0设置重新启动。 仍然没有改变。 编辑 : 在内核2.6.26(和2.6.25)上使用kernel.randomize_va_space=0导致strace legacy-gcc报告的以下brk()调用: […]

我想在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 ),这很棒。 但是这并不能解决我的问题。

为什么虚拟内存地址在不同的进程中是相同的?

我知道虚拟内存在Windows中分离2G(对于内核)/ 2G(对于用户)。 但为什么variables的地址不是连续堆栈? 喜欢0x22ff74,0x22ff78,0x22ff82,0x22ff86? 这是否意味着Windows在用户进程中使用沙盒机制?

我的32位应用程序能做什么,消耗千兆字节的物理内存?

几个月前,一位同事向我提到,我们的一个Delphi应用程序似乎占用了8GB的内存。 我告诉他了: 这是不可能的 一个32位应用程序只有一个32位的虚拟地址空间。 即使有内存泄漏,它可以消耗的最多的内存也是2GB。 之后,分配将失败(因为在虚拟地址空间中不会有空的空间)。 而在内存泄漏的情况下,虚拟页面将被换出到页面文件,释放物理RAM。 但他指出,Windows资源监视器指出,系统上可用的RAMless于1 GB。 而我们的应用程序只使用了220 MB的虚拟内存:closures它释放了8 GB的物理RAM。 所以我testing了它 我让应用程序运行了几个星期,今天我终于决定testing它。 首先我看看closures应用程序之前的内存使用情况: 工作集(RAM)是241 MB 使用的总虚拟内存: 409 MB 我使用资源监视器检查应用程序使用的内存,以及使用的总RAM: 由应用程序分配的虚拟内存: 252 MB 正在使用的物理内存: 14 GB 然后closures应用程序后的内存使用情况: 正在使用的物理内存: 6.6 GB (低7.4 GB) 我还使用Process Explorer来查看物理RAM使用前后的细分情况。 唯一的区别是,8 GB的内存真的没有提交,现在免费: | Item | Before | After | |——————————-|————|———–| | Commit Charge (K) | 15,516,388 | 7,264,420 | | […]