我想使用mmap通过将具有MAP_SHARED标志集的mmap()与固定大小的结构与众所周知的文件名相关联,在Linux下运行的C程序中实现程序状态某些部分的持久性。出于性能原因,我不希望完全不调用msync(),并且没有其他程序将访问此文件。当我的程序终止并重新启动时,它将再次映射相同的文件并对其进行一些处理以恢复终止之前的状态。我的问题是这样的:如果我从不在文件描述符上调用msync(),内核是否保证对内存的所有更新都将写入磁盘,并且即使我的进程以SIGKILL终止,也可以随后恢复。也,
编辑: 我已经解决了是否写入数据的问题,但是我仍然不确定这是否会导致某些意外的系统加载,而试图通过open()/ write()/ fsync()和如果该进程受到KILL / SEGV / ABRT / etc的攻击,则可能会丢失一些数据。添加了“ linux- kernel”标签,以希望某些知识渊博的人可以加入。
我决定不那么懒惰,并通过编写一些代码来回答是否将数据最终写入磁盘的问题。答案是它将被编写。
这是一个程序,将一些数据写入mmap文件后会突然杀死自己:
#include <stdint.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> typedef struct { char data[100]; uint16_t count; } state_data; const char *test_data = "test"; int main(int argc, const char *argv[]) { int fd = open("test.mm", O_RDWR|O_CREAT|O_TRUNC, (mode_t)0700); if (fd < 0) { perror("Unable to open file 'test.mm'"); exit(1); } size_t data_length = sizeof(state_data); if (ftruncate(fd, data_length) < 0) { perror("Unable to truncate file 'test.mm'"); exit(1); } state_data *data = (state_data *)mmap(NULL, data_length, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_POPULATE, fd, 0); if (MAP_FAILED == data) { perror("Unable to mmap file 'test.mm'"); close(fd); exit(1); } memset(data, 0, data_length); for (data->count = 0; data->count < 5; ++data->count) { data->data[data->count] = test_data[data->count]; } kill(getpid(), 9); }
这是一个在上一个程序失效后验证结果文件的程序:
#include <stdint.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include <assert.h> typedef struct { char data[100]; uint16_t count; } state_data; const char *test_data = "test"; int main(int argc, const char *argv[]) { int fd = open("test.mm", O_RDONLY); if (fd < 0) { perror("Unable to open file 'test.mm'"); exit(1); } size_t data_length = sizeof(state_data); state_data *data = (state_data *)mmap(NULL, data_length, PROT_READ, MAP_SHARED|MAP_POPULATE, fd, 0); if (MAP_FAILED == data) { perror("Unable to mmap file 'test.mm'"); close(fd); exit(1); } assert(5 == data->count); unsigned index; for (index = 0; index < 4; ++index) { assert(test_data[index] == data->data[index]); } printf("Validated\n"); }