2

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

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

问题是loadHugeFile函数需要加载一个非常大的千兆字节文件,大约需要 5 分钟,而processTheDataOfTheFile需要不到 10 秒的时间来计算所需的数据并返回一些值。将来,文件的大小可能会进一步增加,加载时间会更长。该文件是一个反向索引,因此需要整个文件。

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

4

4 回答 4

3

您可以使用mmap功能。

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

你有2个优势Extreme speed在加载文件时,内容将位于可以在许多其他进程之间共享的内存区域中(只需mmap与 flag 一起使用MAP_SHARED)。

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

#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 %c\n", p[0], p[1], p[2]);

    close(fd);

    // detach
    munmap(p, sb.st_size);
}
于 2013-02-13T15:58:21.207 回答
2

有不止一种方法可以做到这一点,但直接的方法是映射文件并在其他进程中使用共享内存,以便他们可以访问文件。

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

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

于 2013-02-13T15:58:18.293 回答
1

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

于 2013-02-13T16:05:52.467 回答
1

我猜如果你的文件是多个千兆字节,加载需要很长时间,因为它会溢出 RAM 并导致 RAM 中的数据被推送到硬盘驱动器的交换部分。

实现一次读取文件并将其保存在 ram 中的目标的一种方法是将文件复制到/dev/shm/目录中。中的文件/dev/shm/实际上存储在 RAM 中,可供多个进程使用。但是,如果您的文件量很大或超过系统上的 RAM 量,这仍然会遇到与交换到硬盘驱动器相同的问题,因此我不推荐它。

我建议使用带有mmap的内存映射文件。这为您提供了几个优势:

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

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

于 2013-02-13T16:00:21.533 回答