【问题标题】:The 'length` parameter of msync does not workmsync 的 'length' 参数不起作用
【发布时间】:2017-06-13 10:28:13
【问题描述】:

我将一个文件映射到字符串中。

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 检查)不是我放入 msynclength 参数中的大小,即strlen(rendered),但文件的原始大小,即strlen(f)

然后我尝试通过512 128 或其他方式硬编码分配length,但我发现它们都不起作用。从 mmap 写回文件的大小仍然是 mmaped char 的原始大小。

但在msync的手册中,它说:

文件中对应于从addr开始且长度为length的内存区域的部分被更新。

所以我感到很困惑,谁能告诉我如何分配要刷新回磁盘的地址长度?

【问题讨论】:

  • msync 无法更改底层映射的大小。您只有mmaped 原始文件大小,无法通过映射地址更改大小。
  • 对磁盘的读/写是以块为单位执行的,mmap() 是在读/写的基础上构建的。历史上的块大小是 512 字节,现在通常是 4096 字节。您不能编写部分块。 (您可以截断文件,在这种情况下,只有最后一个块的一部分是 visible
  • 您引用的msync手册页中的“更新”是指“文件中与内存区域对应的部分”,而不是指更新长度。

标签: c linux mmap


【解决方案1】:

感谢那些在 cmets 中启发我的人,对不起,我没有阅读手册。

msync 不能扩展您映射的大小,您也不能mmap 大于文件大小。

所以这是一个想法:

  1. 增加文件大小
  2. 取消映射
  3. 重新映射
  4. msync 重新映射的 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);

它有效!

修改后的文件可以刷回磁盘!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-14
    • 2013-12-19
    • 2012-11-18
    • 2019-07-06
    相关资源
    最近更新 更多