通过mmap写文件,但是当我使用fread时,第二次读取错误数据

时间:2014-06-01 08:46:18

标签: c linux mmap fread

当我使用mmap和memcpy写一个文件,然后我用fread来读取数据。 以下是我的代码,问题是我第一次阅读 a ,但第二次我无法阅读。 我猜有点像fread函数中的搜索位置,当我使用memcpy写文件时,它可能会改变搜索位置。

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

int main()
{


    int fd = open("./aa", O_CREAT | O_RDWR | O_TRUNC, 0644);
    FILE* f = fopen("./aa", "r");
    if (ftruncate(fd, 1024) < 0) {
        printf("ftruncate error\n");
    }
    void* base;
    if ((base = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
        printf("mmap error\n");
    }
    char* file_ptr = (char *)base;
    char buffer[256];
    char scratch[256];
    buffer[0] = 'a';
    memcpy(file_ptr, buffer, 1);
    file_ptr += 1;
    size_t n = fread(scratch, 1, 1, f);
    printf("size n %zu\n", n); // this output size n 1
    printf("scratch %c\n", scratch[0]); // this output scratch a
    memcpy(file_ptr, buffer, 1);
    file_ptr += 1;
    n = fread(scratch, 1, 1, f);
    printf("size n %zu\n", n); // this output size n 1
    printf("scratch %c\n", scratch[0]); // but this output scratch  
    return 0;
}

输出是: 大小n 1 划伤一个 大小n 1 刮

1 个答案:

答案 0 :(得分:2)

首先,@ wildplasser是对的,你的程序可能有效,但是如果你继续混合mmap和stdio,你需要确保通过mmap完成的写入被提交(使用{{1函数)并且fread没有缓冲过时的数据(msync()到当前位置应该这样做。)

来到你的问题:你的程序没有打印“scratch”,它打印“scratch \ 0”:)

说真的,你要做的是通过fseek()初始化“aa”文件的大小,这与填充缺失的字节最多为1024'\ 0';你写一个'a',并阅读它;然后你读了另一个角色,你得到了一个N​​UL。

尝试打印scratch [0]的ascii字符,你会看到它为零;如果您仍然不相信,请尝试添加类似

的内容
ftruncate()

在第一个memcpy之前,看看会发生什么。