tags:

views:

31

answers:

2

I have some code (which I cannot change) that I need to get working in a native Win32 environment. This code calls mmap() and munmap(), so I have created those functions using CreateFileMapping(), MapViewOfFile(), etc., to accomplish the same thing. Initially this works fine, and the code is able to access files as expected. Unfortunately the code goes on to munmap() selected parts of the file that it no longer needs.

x = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
... 
munmap(x, hdr_size);
munmap(x + foo, bar);
...

Unfortunately, when you pass a pointer into the middle of the mapped range to UnmapViewOfFile() it destroys the entire mapping. Even worse, I can't see how I would be able to detect that this is a partial un-map request and just ignore it.

I have tried calling VirtualFree() on the range but, unsurprisingly, this produces ERROR_INVALID_PARAMETER.

I'm beginning to think that I will have to use static/global variables to track all the open memory mappings so that I can detect and ignore partial unmappings, but I hope you have a better idea...

edit:

Since I wasn't explicit enough above: the docs for UnMapViewOfFile do not accurately reflect the behavior of that function.

Un-mapping the whole view and remapping pieces is not a good solution because you can only suggest a base address for a new mapping, you can't really control it. The semantics of munmap() don't allow for a change to the base address of the still-mapped portion.

What I really need is a way to find the base address and size of a already-mapped memory area.

edit2: Now that I restate the problem that way, it looks like the VirtualQuery() function will suffice.

+2  A: 

It is quite explicit in the MSDN Library docs for UnmapViewOfFile:

lpBaseAddress
A pointer to the base address of the mapped view of a file that is to be unmapped. This value must be identical to the value returned by a previous call to the MapViewOfFile or MapViewOfFileEx function.

You changing the mapping by unmapping the old one and creating a new one. Unmapping bits and pieces isn't well supported, nor would it have any useful side-effects from a memory management point of view. You don't want to risk getting the address space fragmented.

You'll have to do this differently.

Hans Passant
Ah, if only documentation could be counted on to be accurate. I had hoped that partial un-mappings would simply fail as implied by what you quoted, but that's not the case.
Tim Sylvester
I'm surprised too. Just never tried it before.
Hans Passant
Doing a free() on a pointer in the middle of an allocated block doesn't simply fail either :-)
Blank Xavier
A: 

You could keep track each mapping and how many pages of it are still allocated by the client and only free the mapping when that counter reaches zero. The middle sections would still be mapped, but it wouldn't matter since the client wouldn't be accessing that memory anyway.

Create a global dictionary of memory mappings through this interface. When a mapping request comes through, record the address, size and number of pages that are in the range. When a unmap request is made, find out which mapping owns that address and decrease the page count by the number of pages that are being freed. When that count reaches zero, really unmap the view.

Chris Smith