代码之家  ›  专栏  ›  技术社区  ›  Mr B

mmap仅适用于小文件?

  •  0
  • Mr B  · 技术社区  · 7 年前

    我正在尝试将文件从本地磁盘映射到内存中,以便我的程序可以访问文件内容。当对文件(大小略低于100kB)调用mmap时,我从mmap返回的地址开始查看调试器中的内存,内存内容与文件内容不匹配(均以十六进制查看)。这是 字节交换问题。只有内存中的前2个字节与实际文件匹配,其余内容不匹配。

    当我在一个包含字符串的小文件(例如:“hello world”)上重复相同的操作时,调试器中查看的内存与文件的内容完全匹配(再次以十六进制查看)。

    我尝试使用MAP\u PRIVATE代替MAP\u SHARED,但结果相同。我怎样才能让它与我的大文件一起工作?

    我在使用Eclipse 4.7.2+CDT的Ubuntu 17.10中工作,并使用GDB进行调试。

    #include <iostream>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string>
    #include <unistd.h>
    #include <sys/mman.h>
    
    int main()
    {
        void* MapAddr = NULL;
        char* pData = NULL;
        struct stat FileProps;
        int FileDes = 0;
        const char* fileNameAndPath = "/home/Test/testfile.txt";
    
        FileDes = open(fileNameAndPath, O_RDWR);
    
        if (FileDes != -1)
        {
            if (fstat(FileDes, &FileProps) == 0)
            {
                MapAddr = mmap(NULL, FileProps.st_size, (PROT_READ | PROT_WRITE), MAP_SHARED, FileDes, 0);
                if (MapAddr == (void*) -1)
                {
                    std::cout << "init: mmap failed" << std::endl;
                    return 0;
                }
            }
        }
        pData = (char*) MapAddr;
        std::cout << pData << std::endl;
        return 0;
    }
    

    13: 10:42****为项目mmapTest构建配置调试**** 全部生成 正在生成文件:/src/mmapTest。cpp公司 调用:GCC C++编译器 g++-O0-g3-Wall-c-F消息长度=0-MMD-MP-MF“src/mmapTest.d”-MT“src/mmapTest.o”-o“src/mmapTest.o”“../src/mmapTest.cpp” 完工建筑:/src/mmapTest。cpp公司

    建设目标:mmapTest 调用:GCC C++链接器 g++-o“mmapTest”/src/mmapTest。o
    完工建筑目标:mmapTest

    13: 10:46构建完成(耗时4s.438ms)

    2 回复  |  直到 7 年前
        1
  •  1
  •   BJovke    7 年前

    mmap() 不会实际将整个文件读取到内存中,也不会实际分配文件大小RAM量。它只分配足够大的虚拟地址空间来“容纳”其中的文件。

    它的工作原理是使用页面错误,当您尝试读取文件的某个区域时,将分配实际RAM(或重用某些其他页面),并将一定数量的页面数据从文件读取到内存中。

    您很难将整个文件加载到ram中 mmap() 。但无论何时您尝试读取或写入数据(从程序、, 从调试器)一切正常。


    是的,最重要的是, mmap() 工作方式与 CreateFileMapping() 因此,您应该可以移植代码。

        2
  •  0
  •   Mr B    7 年前

    运行mmap()后,我确定内存内容(在GDB调试器中查看)与实际文件内容不匹配的原因是我映射的文件不是ANSI编码的。因此,调试器显示了Linux认为应该显示的正确数据。以ANSI格式保存文件(在textpad中)后,Linux中查看的文件二进制内容与Windows中查看的二进制内容相同。无需更改代码。问题在于正在映射的文件。与其中一条注释相反,GDB调试器能够使用内存查看器在mmap()返回的地址显示所有映射的文件数据-我已经确认了100KB以下的文件。