在Linux下的C / C ++中,为了存储来自连接到以太网端口的传感器的实时数据,并以大约110MB / s的速率stream式传输数据,我需要分配一个大的(几个千兆字节)内存块。 我想分配尽可能多的内存,以最大化我可以存储的数据序列的长度。 但是,我还需要确保不会有磁盘交换,因为由此产生的延迟和有限的磁盘访问带宽会导致传感器(非常有限)的缓冲区溢出。
确定要分配多less内存的最佳方法是什么? 我仅限于分配一个比报告的空闲内存稍小的块,或者我可以更直接地与Linux虚拟内存pipe理器接口吗?
那么,在Linux下,你可以使用mlock()/ mlockall()在物理内存中保留一个地址范围,并防止它被换出。 使用mlock的过程需要一些特权才能这样做,“man mlock”具有细节。 我不确定最大的mlock'able块(它可能不同于什么似乎是“免费”),所以可能二进制搜索可以帮助(锁定一个范围,如果不能减小面积的大小等)。
另一方面,对于固态硬盘来说,110MB / s并不是一个问题。 写入速度为280MB / s的60GB固态硬盘在角落费用约为200美元。 只需将传感器数据复制到一个小的写入缓冲区并将其传输到SSD即可。
如果计算机系统专门从您的传感器接收数据,您可以简单地禁用交换。 然后,尽可能地分配一个大的缓冲区,留下足够的内存在系统中只有必要的工具。
如果以这样的速度分配所需的内存量并写入内存,则由于所有页面错误(即,将每个虚拟内存页面映射到物理内存,也可能包括交换内存其他进程)。
为了避免这种情况,您可以在开始从传感器读取数据之前将整个分配的缓冲区memset
为0,以便将所有需要的虚拟内存映射到物理内存。
如果只使用可用的物理内存,则根本不应该交换。 使用more会导致其他进程的内存被交换到磁盘 – 如果这些进程是空闲的,它不应该造成任何问题。 如果它们处于活动状态(即偶尔使用它们的内存),则会发生一些交换 – 可能比硬盘带宽低得多。 您使用的内存越多,更活跃的进程内存就会被换出,而更多的高清活动将会发生 – 在这一点上,您可以使用的最大内存量与体面的性能相当,是相当多的尝试和错误的结果。
通过使用超过可用的物理内存,你肯定会导致内存写入速度的交换,而且没有办法避免这种情况。
确定要分配多少内存的最佳方法是什么?
由于如何使用虚拟内存,不可交换内核内存,几乎不可能确定应用程序可以访问多少安装的内存。
最好的我可以想出的是允许用户配置多少内存用于缓冲。
我只限于分配一个比报告的空闲内存略小的块,
报告的空闲内存不是真正的“免费物理内存”。 不幸。
或者我可以更直接地与Linux虚拟内存管理器接口?
这可以通过使用自定义设备驱动程序来完成,直接在内核空间分配内存并通过mmap()
访问它。 一般不推荐,但会在你的特殊情况下工作。
但是,我还需要确保不会有磁盘交换
随着Linux内核发展的步伐,知识变得相当快速,所以我要说的是, 你可以尝试玩下面的内容:
SysV共享内存。 它通常不会交换。 见man shmget
。
tmpfs – 内存中的文件系统。 内存至少在2.6内核固定到内存,因此不可交换。 要使用它作为内存,在tmpfs上创建一个文件,在文件中write()
一些东西(强制内存被分配),然后mmap()文件。
分配你的记忆后,你可以
echo 0 > /proc/sys/vm/swappiness
要求内核倾向于从缓存中回收内存而不是交换。
只是我的0.2美元