简体   繁体   中英

The 'length` parameter of msync does not work

I mmap a file into String.

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);

then I cJSON parse the f and do some modification.

cJSON *root = cJSON_Parse(f);
//some JSON operation

After finish I regenerated the string from cJSON and try to write it back to disk.

char* rendered = cJSON_Print(root);
memcpy(f, rendered, strlen(rendered));
msync(f, strlen(renderer), MS_SYNC);

There is no error in either mmap or msync.

I checked the file content and found it changes correctly as what I modify using cJSON library.

However, the file is not completed. To be more specific, the size it wrote back to the disk (I check it using Sublime) is not the one I put in the length parameter of msync ,ie strlen(rendered) , but the original size of the file, ie strlen(f) .

Then I tried to assign the length hardcodedly by 512 128 or whatever, but I found all of them do not work. The size write back to the file from mmap is still the original size of the mmaped char.

But in the manual of msync , it says:

The part of the file that corresponds to the memory area starting at addr and having length length is updated.

So I feel puzzled and can anyone tell me how I can assign the length of address I want to flush back to disk?

Thanks for the people inspiring me in the comments, sorry I did a poor reading of the manual.

The msync cannot extend the size you mapped, you cannot mmap more size than the file size neither.

So here is the idea:

  1. increase the filesize
  2. unmap
  3. remmap
  4. msync the remapped f with new content

There for I implemented the resize_remap function

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
}

Then the program is like:

char* rendered = cJSON_Print(root);
file_remap_resize(&fd, &f, strlen(rendered));
memcpy(f, rendered, strlen(rendered));
msync(f, strlen(renderer), MS_SYNC);

and it works!

The modified file can be flushed back into the disk!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM