搜索
linux - mmap映射的文件保存之后重新打开,为什么除了前几个字节之外数据都丢失了?
ringa_lee
ringa_lee 2017-04-17 13:05:52
[Linux讨论组]

我正在写一个简单的本地缓存,我希望将缓存的内容映射到硬盘文件上。但是我重新打开这个文件之后发现除了开头的几个字节之外,其他部分的数据全部丢失了(变成0).
以下是文件映射部分的源码(C++):

    template <typename K, typename V>
    void *cache<K, V>::attachFile(const char *pathname, size_t length) {
        int fd;
        struct stat statbuff;
        if (stat(pathname, &statbuff) == -1) {
            fd = open(pathname, O_RDWR|O_CREAT|O_EXCL, 0644);
            if (fd == -1)
                errexit("open O_CREAT");
            if (ftruncate(fd, length) == -1) {
                close(fd);
                errexit("ftruncate");
            }
        }
        else {
            if (static_cast<size_t>(statbuff.st_size) != length)
                errexit("length is not correct.");
            fd = open(pathname, O_RDWR);
            if (fd == -1)
                errexit("open O_RDWR");
        }
        void *addr = mmap(NULL, length, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
        close(fd);
        if (addr == MAP_FAILED)
            errexit("mmap");
        //  return NULL;
        return addr;
    }

    template <typename K, typename V> 
    void cache<K, V>::releaseFile(void *addr, size_t length) {
        if (addr != NULL && length != 0) {
            if (msync(addr, length, MS_SYNC) == -1) 
                errexit("msync");
            if (munmap(addr, length) == -1) 
                errexit("munmap");
        }
    }

完整代码在https://github.com/choleraehyq/lightcache
我的开发平台是ubuntu14.04,编译器是G++4.9.2,查看了APUE没有发现什么问题,请问这可能是什么原因造成的呢?

ringa_lee
ringa_lee

ringa_lee

全部回复(1)
阿神

楼主,做了单元测试了么?我用你的代码测了一下,没有问题啊:

#include <fcntl.h> // for open
#include <unistd.h> // for close ftruncate
#include <sys/mman.h> // for mmap
#include <sys/stat.h> // for stat

#include <stdio.h> // for perror
#include <stdlib.h> // for exit
#include <stdint.h> // for uint8_t

void reportErrorAndExit(const char* msg, const char* file, int line)
{
    fprintf(stderr, "[%s: %d]", __FILE__, __LINE__);
    perror(msg);
    exit(-1);
}

#define errexit(msg) reportErrorAndExit(msg, __FILE__, __LINE__)

    void *attachFile(const char *pathname, size_t length) {
        int fd;
        struct stat statbuff;
        if (stat(pathname, &statbuff) == -1) {
            fd = open(pathname, O_RDWR|O_CREAT|O_EXCL, 0644);
            if (fd == -1)
                errexit("open O_CREAT");
            if (ftruncate(fd, length) == -1) {
                close(fd);
                errexit("ftruncate");
            }
        }
        else {
            if (static_cast<size_t>(statbuff.st_size) != length)
                errexit("length is not correct.");
            fd = open(pathname, O_RDWR);
            if (fd == -1)
                errexit("open O_RDWR");
        }
        void *addr = mmap(NULL, length, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
        close(fd);
        if (addr == MAP_FAILED)
            errexit("mmap");
        //  return NULL;
        return addr;
    }

    void releaseFile(void *addr, size_t length) {
        if (addr != NULL && length != 0) {
            if (msync(addr, length, MS_SYNC) == -1) 
                errexit("msync");
            if (munmap(addr, length) == -1) 
                errexit("munmap");
        }
    }

int main(int argc, char* argv[])
{
    if(argc < 3) {
        fprintf(stderr, "usage: %s file length\n", argv[1]);
        return -1;
    }

    size_t length = static_cast<size_t>(atol(argv[2]));
    uint8_t* addr = static_cast<uint8_t*>(attachFile(argv[1], length));

    for(size_t i = 0; i < length; ++i) {
        addr[i] = i & 0xff;
    }

    releaseFile(addr, length);

    return 0;
}

建议楼主:建议楼主单独测一下这两个方法,再检查一下其他部分的代码。
我的环境:Ubuntu 12.04, g++ 4.6.3

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号