为什么这个文件映射变量不刷新到磁盘?
Why doesn't this file-mapped variable get flushed to the disk?
最近发现自己的C技能有点生疏了,决定玩一玩。不过,我只是遇到了一个奇怪的行为——我请求的文件映射内存似乎没有刷新变量 ifs.free_space
。结果是,如果不注释掉 //root
这两行,程序总是以 ifs.free_space
等于 0 开始。但是,将其注释掉会导致计数器被保存。这里发生了什么?
#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
结构的位置重叠。这是因为您从 free_space
开始于 0,因此第一个 root
结构将分配在偏移量 0 处,正好是 ifs
结构所在的位置。
在分配第一个 root
结构之前,您应该将 free_space
设置为 sizeof(ifs)
。
最近发现自己的C技能有点生疏了,决定玩一玩。不过,我只是遇到了一个奇怪的行为——我请求的文件映射内存似乎没有刷新变量 ifs.free_space
。结果是,如果不注释掉 //root
这两行,程序总是以 ifs.free_space
等于 0 开始。但是,将其注释掉会导致计数器被保存。这里发生了什么?
#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
结构的位置重叠。这是因为您从 free_space
开始于 0,因此第一个 root
结构将分配在偏移量 0 处,正好是 ifs
结构所在的位置。
在分配第一个 root
结构之前,您应该将 free_space
设置为 sizeof(ifs)
。