c - 为什么这个文件映射变量没有刷新到磁盘?

标签 c file-mapping

我最近意识到我的 C 技能有点生疏了,决定玩一下。但我最终遇到了一个奇怪的行为 - 我请求的文件映射内存似乎没有刷新变量 ifs.free_space。结果是,如果您不注释掉两行 //root 行,则程序始终以等于 0 的 ifs.free_space 开头。但是,将其注释掉会导致计数器被保存。这里发生了什么?

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>

#define FILE_LENGTH 0x10000


void* offset_to_pointer(uint64_t offset, void* file_memory) {
    return (void *)((uint64_t)file_memory + offset);
}

uint64_t pointer_to_offset(void* pointer, void* file_memory) {
    return ((uint64_t)pointer - (uint64_t)file_memory);
}

void* allocate(uint64_t size, uint64_t* free_space, void* file_memory) {
    void* ret = offset_to_pointer(*free_space, file_memory);
    *free_space += size;
    return ret;
}

typedef struct dirent {
    uint64_t prev_offset;
    uint64_t next_offset;
    uint64_t size;
} dirent;

typedef struct idiotfs {
    void* file_memory;
    uint64_t* free_space;
    dirent* root;
} idiotfs;

int main (int argc, char* const argv[])
{
    int fd = open("file.bin", O_RDWR | O_DSYNC, S_IRUSR | S_IWUSR);
    if (fd == -1)
        return 2;
    idiotfs ifs;
    ifs.file_memory = mmap(0, FILE_LENGTH,
                           PROT_READ | PROT_WRITE,
                           MAP_SHARED, fd, 0);
    ifs.free_space = (uint64_t *)offset_to_pointer(0, ifs.file_memory);
    dirent* root = (dirent *)allocate(sizeof(struct dirent) + strlen("hi") + 1,
                                      ifs.free_space, ifs.file_memory);
    //root = (dirent *)allocate(sizeof(struct dirent) + strlen("hi") + 1,
    //                          ifs.free_space, ifs.file_memory);
    root->prev_offset = 0;
    root->next_offset = 0;
    root->size = 3;
    char* text = (char *)((uint64_t)root + sizeof(dirent));
    strcpy(text, "hi");
    close(fd);
}

最佳答案

重叠结构

ifs 结构的位置与第一个 root 结构的位置重叠。这是因为您从 0 开始 free_space ,因此第一个 root 结构将被分配在偏移量 0 处,正是 ifs 结构所在的位置。

在分配第一个 root 结构之前,应将 free_space 设置为 sizeof(ifs)

关于c - 为什么这个文件映射变量没有刷新到磁盘?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30089238/

相关文章:

c++ - 复制内存块

c - 如何读取 send(sock_fd, line, size, 0);?

c - 使用 "FindFirstFileA"- C 查找目录中的所有文件

c - 线性归一化段错误和内存错误

c++ - 如何通过 MapViewOfFile 发送 vector<vector<type>>

c++ - 在不使指针无效的情况下在 Windows 上调整内存映射文件的大小

c++ - 使用 MapViewOfFile 映射大文件

java - 在 Java 中使用并发在磁盘上创建键值存储

c - gcc 编译器中结构的大小

C - 使用 fgetc 读取文件末尾