12

在 Linux 下的 C/C++ 中,我需要分配一个大的(几千兆字节)内存块,以便存储来自连接到以太网端口的传感器的实时数据和大约 110MB/s 的流数据。我想分配尽可能多的内存,以最大化我可以存储的数据序列的长度。但是,我还需要确保不会发生磁盘交换,因为由此产生的延迟和磁盘访问的有限带宽会导致传感器的(非常有限的)缓冲区溢出。

确定要分配多少内存的最佳方法是什么?我是否仅限于分配比报告的可用内存略小的块,还是可以更直接地与 linux 虚拟内存管理器交互?

4

4 回答 4

10

好吧,在 linux 下,您可以使用 mlock()/mlockall() 将地址范围保留在物理内存中并防止它被换出。使用 mlock 的过程需要几个特权才能这样做,“man mlock”有详细信息。我不确定最大 mlock'able 块(它可能与看似“免费”的块不同),所以可能二进制搜索可能会有所帮助(锁定范围,如果失败减少区域的大小等。)

另一方面,对于固态驱动器来说,110MB/s 并不是真正的问题。具有 280MB/s 写入速度的 60GB SSD 售价约为 200 美元。只需将传感器数据复制到一个小的写入缓冲区并将其流式传输到 SSD。

于 2010-07-14T11:43:09.213 回答
3

如果计算机系统专用于从传感器接收数据,您可以简单地禁用交换。然后分配尽可能大的缓冲区,在系统中留出足够的内存仅用于基本工具。

于 2010-07-14T11:51:18.087 回答
0

如果您malloc需要的内存量并以该速度写入它,由于所有页面错误(即将虚拟内存的每一页映射到物理内存,这也可能包括换出其他内存),您仍然会受到性能影响过程)。

为了避免这种情况,您可以memset在开始从传感器读取之前将整个分配的缓冲区设置为 0,以便将所有需要的虚拟内存映射到物理内存。

如果您只使用可用的物理内存,那么您根本不会遭受交换。使用更多会导致其他进程的内存被交换到磁盘 - 如果这些进程空闲,它不应该造成任何问题。如果它们处于活动状态(即偶尔使用它们的内存),则会发生一些交换 - 可能以比硬盘驱动器带宽低得多的速率。您使用的内存越多,将换出更多活动进程的内存,并且会发生更多的 HD 活动 - 此时,您可以使用的最大内存量具有良好的性能几乎是反复试验的结果。

通过使用超过可用物理内存,您肯定会导致以内存写入速率进行交换,并且没有办法避免这种情况。

于 2010-07-14T11:30:54.030 回答
0

确定要分配多少内存的最佳方法是什么?

由于虚拟内存的使用方式,不可交换的内核内存,几乎不可能确定应用程序可以访问多少已安装的内存。

我能想到的最好的办法是允许用户配置用于缓冲的内存量。

我是否仅限于分配比报告的可用内存略小的块,

报告的空闲内存并不是真正的“空闲物理内存”。很遗憾。

或者我可以更直接地与 linux 虚拟内存管理器交互吗?

这可以通过使用自定义设备驱动程序、直接在内核空间中分配内存并通过mmap(). 通常不推荐,但适用于特殊情况,例如您的情况。

但是,我还需要确保不会进行磁盘交换

在 Linux 内核开发的步伐中,知识很快就过时了,所以对我在这里所说的话持保留态度。您可以尝试使用以下内容:

  1. SysV 共享内存。一般不换。见man shmget

  2. tmpfs - 内存文件系统。至少在早期的 2.6 内核中,内存被固定到 RAM,因此不可交换。要将其用作内存,请在 tmpfs 上创建一个文件,write()在文件中添加一些内容(以强制实际分配内存),然后 mmap() 文件。

于 2010-07-14T11:38:13.563 回答