Boost logo

Boost Users :

Subject: Re: [Boost-users] [Interprocess] [file_mapping] is there any way to avoid writing a modified file to disc?
From: Ion Gaztañaga (igaztanaga_at_[hidden])
Date: 2011-12-07 11:43:22


El 07/12/2011 16:21, Thorsten Ottosen escribió:
> Den 07-12-2011 16:13, Ion Gaztañaga skrev:
>> El 07/12/2011 14:44, Dean Michael Berris escribió:
>>> Actually, I just checked the docs: it seems you want the
>>> 'copy_on_write' mode which combines PROT_WRITE|PROT_READ and
>>> MAP_PRIVATE. This allows you to make changes in place to the memory
>>> region without having the changes reflected to the original file.
>>
>> Yes, copy_on_write should work. When a page is modified the OS creates a
>> new page for you but other process sees your changes (well, I guess they
>> can end in the page file).
>
> Well, at least with 1.45 I cannot get it to work.

Can you send me an example? (Are you using managed_mapped_file or
mapped_region?) Maybe the bug it still there.

> I also speculate if its actually any faster, since I need to change
> every single byte in the memory region (I'm decrypting).
>
> My understanding of these OS features are weak, but my mental model of
> it is that
>
> //Create a file mapping
> file_mapping m_file( file.c_str(), boost::interprocess::read_only );
>
> //Map the whole file with read-write permissions in this process
> mapped_region region( m_file, boost::interprocess::read_only );
>
> //Get the address of the mapped region
> const char* addr = static_cast<char*>(region.get_address());
> const size_t size = static_cast<int>(region.get_size());
>
> makes the whole file avaiable as one big memory segment.

Yes, but in this case modifying the data should segfault (you are
mapping the memory as read-only, trying to write it will make your MMU
act). You can do this (at least this works in the latest version):

#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <cstddef> //std::size_t
#include <cassert>
#include <fstream>
#include <cstring> //memset
#include <cstdlib> //remove

static char zeros [256];

int main()
{
    using namespace boost::interprocess;
    //Create a file with zeros
    std::remove("myfile");
    {
       std::ofstream f("myfile", std::ios_base::binary);
       f.write(&zeros[0], sizeof(zeros));
    }
    {
       file_mapping fmapping("myfile", read_only);
       mapped_region mregion(fmapping, copy_on_write);
       char* const orig_addr = static_cast<char*>
          (mregion.get_address());
       const std::size_t orig_size =
          static_cast<int>(mregion.get_size());

       char* addr = orig_addr;
       std::size_t size = orig_size;

       ///File is not modified, but we
       while(size--){
          assert(*addr == 0);
          *addr++ = 1;
       }
       assert(*orig_addr != 0);
       //The OS discards changes
    }
    {
       std::ifstream f("myfile", std::ios_base::binary);
       f.read(&zeros[0], 1);
       assert(zeros[0] == 0);
    }
    std::remove("myfile");

    //
    return 0;
}

> It seems to me that the OS must do something to write changed data to
> disc (that is, there is an implicit flush() in one of the destructors).
> Hence I assumed that it would be possible to avoid this flush, leaving
> the file intact.

In theory, when mapping something copy on write, the OS will discard
modified pages. The original file/shared memory shoud never be modified.

Ion


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net