msync 的“长度”参数不起作用
The 'length` parameter of msync does not work
我将一个文件映射到字符串中。
int fd = open(FILE_PATH, O_RDWR);
struct stat s;
int status = fstat(fd, &s);
char *f = (char*) mmap (0, s.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
然后我用 cJSON 解析 f
并做一些修改。
cJSON *root = cJSON_Parse(f);
//some JSON operation
完成后我从 cJSON 重新生成字符串并尝试将其写回磁盘。
char* rendered = cJSON_Print(root);
memcpy(f, rendered, strlen(rendered));
msync(f, strlen(renderer), MS_SYNC);
mmap 或 msync 都没有错误。
我检查了文件内容,发现它正确地更改为我使用 cJSON 库修改的内容。
但是,文件还没有完成。更具体地说,它写回磁盘的大小(我使用 Sublime 检查它)不是我在 msync
的 length
参数中输入的大小,即strlen(rendered)
,但文件的原始大小,即 strlen(f)
.
然后我尝试通过 512
128
或其他方式硬编码分配 length
,但我发现它们都不起作用。从mmap写回文件的大小仍然是mmaped char的原始大小。
但是在msync
的手册中说:
The part of the file that corresponds to the memory area starting at addr and having length length is updated.
所以我感到很困惑,谁能告诉我如何分配我要刷新回磁盘的地址长度?
感谢在评论中鼓励我的人,抱歉我没有阅读手册。
msync
无法扩展您映射的大小,您也不能 mmap
超过文件大小。
想法是这样的:
- 增加文件大小
- 取消映射
- 重新映射
- 将重新映射的 f 与新内容同步
我实现了resize_remap
功能
result_t file_remap_resize(int* fd, char** f, int new_size){
if(ftruncate(*fd, new_size) == -1){
printf("failed to resize\n");
return ERR_CODE;
}
if(munmap(*f, sizeof(*f)) == -1){
printf("failed to unmap\n");
return ERR_CODE;
}
*f = (char*)mmap (0, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(!f){
printf("failed to remap\n");
return ERR_CODE;
}
return SUCCESS
}
那么程序是这样的:
char* rendered = cJSON_Print(root);
file_remap_resize(&fd, &f, strlen(rendered));
memcpy(f, rendered, strlen(rendered));
msync(f, strlen(renderer), MS_SYNC);
而且有效!
修改后的文件可以刷新回磁盘!
我将一个文件映射到字符串中。
int fd = open(FILE_PATH, O_RDWR);
struct stat s;
int status = fstat(fd, &s);
char *f = (char*) mmap (0, s.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
然后我用 cJSON 解析 f
并做一些修改。
cJSON *root = cJSON_Parse(f);
//some JSON operation
完成后我从 cJSON 重新生成字符串并尝试将其写回磁盘。
char* rendered = cJSON_Print(root);
memcpy(f, rendered, strlen(rendered));
msync(f, strlen(renderer), MS_SYNC);
mmap 或 msync 都没有错误。
我检查了文件内容,发现它正确地更改为我使用 cJSON 库修改的内容。
但是,文件还没有完成。更具体地说,它写回磁盘的大小(我使用 Sublime 检查它)不是我在 msync
的 length
参数中输入的大小,即strlen(rendered)
,但文件的原始大小,即 strlen(f)
.
然后我尝试通过 512
128
或其他方式硬编码分配 length
,但我发现它们都不起作用。从mmap写回文件的大小仍然是mmaped char的原始大小。
但是在msync
的手册中说:
The part of the file that corresponds to the memory area starting at addr and having length length is updated.
所以我感到很困惑,谁能告诉我如何分配我要刷新回磁盘的地址长度?
感谢在评论中鼓励我的人,抱歉我没有阅读手册。
msync
无法扩展您映射的大小,您也不能 mmap
超过文件大小。
想法是这样的:
- 增加文件大小
- 取消映射
- 重新映射
- 将重新映射的 f 与新内容同步
我实现了resize_remap
功能
result_t file_remap_resize(int* fd, char** f, int new_size){
if(ftruncate(*fd, new_size) == -1){
printf("failed to resize\n");
return ERR_CODE;
}
if(munmap(*f, sizeof(*f)) == -1){
printf("failed to unmap\n");
return ERR_CODE;
}
*f = (char*)mmap (0, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(!f){
printf("failed to remap\n");
return ERR_CODE;
}
return SUCCESS
}
那么程序是这样的:
char* rendered = cJSON_Print(root);
file_remap_resize(&fd, &f, strlen(rendered));
memcpy(f, rendered, strlen(rendered));
msync(f, strlen(renderer), MS_SYNC);
而且有效!
修改后的文件可以刷新回磁盘!