将数据保留在RAM中,同时允许其他进程在linux C++中访问它

Retain a data in the RAM, while allowing other process to access it in linux C++

本文关键字:其他 进程 linux C++ 访问 RAM 保留 数据 许其他      更新时间:2023-10-16

目前我正在linux中调试一个程序,它看起来像这样:

int main(){
    loadHugeFile();
    processTheDataOfTheFile();
    return 0;
}

问题是loadHugeFile函数需要加载一个以GB为单位的巨大文件,大约需要5分钟,而processTheDataOfTheFile需要不到10秒的时间来计算所需的数据并返回一些值。在未来,文件的大小可能会进一步增加,加载将需要更多的时间。该文件是一个反转索引,因此需要整个文件。

是否可以让一个进程将此文件加载到RAM中,保留它,并让任何其他进程访问加载文件的这一部分?这是为了跳过那么多分钟的加载。我记得Windows有这个功能,可以让你访问/修改另一个进程的内存,但在linux中,我有什么可用的选择?

您可以使用mmap函数。

在计算中,mmap(2)是一个符合POSIX的Unix系统调用,它将文件或设备映射到内存中。这是一种内存映射文件I/O的方法。

您获得了2个优势。加载文件中的Extreme speed,并且内容将在可以在许多其他进程之间共享的存储区域中(只需使用带有标志MAP_SHAREDmmap)。

你可以用这个简短而肮脏的代码来测试mmap的速度。只需编译它并执行它,将要加载的文件传递为paramenter。

#include <stdio.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
    struct stat sb;
    int fd = open(argv[1], O_RDONLY);
    // get the size in bytes of the file
    fstat (fd, &sb);
    // map the file in a memory area
    char *p = mmap (0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
    // print 3 char of the file to demostrate it is loaded ;)
    printf("first 3 chars of the file: %c %c %cn", p[0], p[1], p[2]);
    close(fd);
    // detach
    munmap(p, sb.st_size);
}

有不止一种方法可以做到这一点,但一种直接的方法是对文件进行mmap,并在其他进程之间使用共享内存,以便它们可以访问该文件。

您还可以围绕文件本身实现一个高级套接字读/写API,并允许用户通过API访问它但是,您可能需要考虑将文件加载到SQL数据库或其他文件中,以便在可能的情况下使用实际的数据库后端因为它们是为这类事情设计的。

如果您需要检测文件的更改,可以使用inotify/dnotify

我猜,如果你的文件是多个GB,加载时间会很长,因为它会溢出RAM,导致RAM中的数据被推送到硬盘的交换部分。

实现一次性读取文件并将其保存在ram中的一种方法是将文件复制到/dev/shm/目录。/dev/shm/中的文件实际上存储在RAM中,并且可用于多个进程。如果你的文件数量很大,或者超过了你系统上的RAM数量,这仍然会遇到交换到硬盘驱动器的相同问题,所以我不建议这样做。

我建议使用带有mmap的内存映射文件。这给了你几个优势:

  • 该文件看起来和寻址方式就像RAM中的一个数据数组
  • 只有当前正在读取的文件部分才会加载到RAM中
  • 操作系统负责从ram中提取数据,并将其推回磁盘,因此一旦设置好,就很容易使用

另一种选择是更新您的处理功能,使其在流模式下运行,这可能是可能的,也可能是不可能的。

跳出框框思考,为什么不使用数据库呢?数据库针对搜索大文件进行了优化,由于缓存,它们将在内存中保留部分文件以获得更好的性能。多个进程可以同时访问该文件。