I have an DLL that might get called by multiple applications at the same time.
This DLL memory-maps a file.
I have 2 questions:
1) Each application will create its own instance of the DLL, right?
And thus, the file will be memory-mapped multiple times
2) If this is true, I don't understand what is happening here:
a) Application A calls the DLL.
b) Application B calls the DLL.
c) I quit application A, and the DLL will unmap the file.
d) Application B calls the DLL, and the memory-mapped file is not available anymore, and the call fails.
I don't understand this.
Does anybody do?
Thank you.
This happens because your assumption from 1) is false. A dll is by definition shared; both applications are using the same dll instance, so when you release the file in one application, it won't be available to the others.
To get around your issue, you should implement some reference counting mechanism in order to unmap the file only when no process is using it.
Edit: #sumeet is right. Each process has its own address space; when two processes load the same dll, they might share its read-only data for increased efficiency, but their writable data is local to each process. Nevertheless, a memory-mapped file is a kernel object, like semaphores, pipes and shared memory. Thus, if you unmap it in a process, you unmap it for all.
Edit2: From MSDN (Remarks section):
Multiple processes can share a view of the same file by either using a
single shared file mapping object or creating separate file mapping
objects backed by the same file. A single file mapping object can be
shared by multiple processes through inheriting the handle at process
creation, duplicating the handle, or opening the file mapping object
by name. For more information, see the CreateProcess, DuplicateHandle
and OpenFileMapping functions.
[...]
Mapped views of a file mapping object maintain internal references to
the object, and a file mapping object does not close until all
references to it are released. Therefore, to fully close a file
mapping object, an application must unmap all mapped views of the file
mapping object by calling UnmapViewOfFile and close the file mapping
object handle by calling CloseHandle. These functions can be called in
any order.
First of all, from the first paragraph, how is each app initializing the view?
From the second paragraph, I gather that calling UnmapViewofFile and CloseHandle from each app will release all references to the memory file, and then Windows will automatically release the associated resources (i.e. he keeps the reference count, you don't need to do it).
Post your memory mapping initialization and shutdown code for both apps.
Related
I'm using Boost shared memory to share vectors across different processes. However, on some occasions, the consumer of the shared memory throws up this exception:
Unexpected exception: The volume for a file has been externally altered so that the opened file is no longer valid.
I have the proper Synchronization mechanism set in place. What could this error indicate?
SOLVED Size of the memory hadn't been properly allocated upon creation by one of the processes.
When a shared memory object is created, its size is 0. To set the size of the shared memory, the user must use the truncate function call, in a shared memory that has been opened with read-write attributes
Source - Boost shared memory
It means the volume for a file has been externally altered. Look for other processes writing the file.
In other words, it means you do not have proper synchronization in place.
Do you use bip::managed_mapped_file::grow by any chance? The documentation states it only allows offline growing.
I have a huge program (A) which uses about 30 (most of my own, some 3rd party) dll´s. It uses ActiveX, ATL and MFC to do different stuff. Now i want to use wxWidgets for some special tasks and will call the wxWidgets dialogs from within the program. I can do this with a special designed DLL which takes the wxW.. parts. But to run the special tasks with or without the A programm i would to like to put the wxW.. stuff in an exe (B) and these exe should address the same data from the A program. As far as i know each *.exe has its own process and so i can not share the same pointer address.
I can put in some shared data block in one of the DLLs.
#pragma data_seg("SHARED")
CClassA *g_ClassAPointer=NULL;
#pragma data_seg()
#pragma comment(linker, "/section:SHARED,RWS")
If the A is running and starts B, i can get the pointer g_ClassAPointer with the address within A. Is there a way to get the address or get an offset to reach this address within B ?
Thanks in advance,
Howie
BTW: We also want to use wxWidgets to fade all the MFC stuff more and more to cross platform code otherwise i would stick to MFC or use the wxW - DLL within a wrapper *.exe.
You're looking for shared memory, and the usual way to create that is via CreateFileMapping. This can create shared memory backed by a named file, or backed by the paging file. (Memory allocated by GlobalAlloc is also backed by the paging file, so that's no unusual thing).
In either case, the memory block from CreateFileMapping is named, so another process can access the shared memory block by calling OpenFileMapping with the same name.
Keep in mind that the shared memory block might reside at different offsets in memory. Also, if you put CClassA in shared memory, there's no automatic mechanism to ensure that all pointers inside CClassA point to the same shared memory block. E.g. putting a std::string or MFC CString in shared memory is unlikely to achieve what you intended.
I'm very new to Memory Mapped Files, and I'm a little lost on something.
I know that if I had a file, I could load it and access it from various processes at once using MMaps.
But in my situation, I'm creating a DLL attached to Process A, and that DLL has been given a pointer to a cSurface which Process A has prepared. I need to share that cSurface's data with Process B. I really don't want to have to call up a blank MMap and copy my Process A's surface into it, only to copy it out again in process B.
Is it possible to map my surface as if it were a file so the MMap already points to the surface data when it's created (as it would were I loading SomeTextFile.txt)?
My plan, in theory, would be to receive a pointer to the surface in Proc A, tell windows to share that surface's memory with a given name, and use Mutexes to coordinate access - the idea being that both processes read the same physical copy of the surface with no cumbersome copying.
Is that possible?
Yes, it's all there in the documentation of CreateFileMapping.
You can give your memory mapped file a name. If another process open a mmap with the same name it will point to the same memory. It the handle in CreateFileMapping is put to INVALID_HANDLE_VALUE it keeps it purely in memory. Check the documentation of CreateFileMapping
Thanks for all your comments.
I did some further research and found the answer.
You can use Memory Mapped Files to share either a file, or a blank memory space. If you want to share data already initialised in memory prior to setting up the map, you have to create a blank map and subsequently copy your data into it.
I have a shared library say foo.so which contains a function called initialize(). There are multiple executables that open foo.so and each calls initialize(). I would like initialize() to check if it has already been called by another executable and if so do nothing. What's the best way of sharing this information between these processes? Is there some special facility to share such information or do I need to use standard IPC?
Create a file /var/db/mylibname. If open() returns an error saying that the file already exists, then your library was initialized.
It'll require to add atexit() handler that will remove the file when process exits. Atexit must be initialized only if open() returns success.
UPDATE:
If resources must be initialized only once and if they (resources) don't depend on the existence of any process that uses the library at the time, then it's better to create file in /var/run directory (so that it is cleaned up after system reboot) and forget about atexit().
You need to use standard IPC. Memory mapping comes to mind, but first decide whether you want initialization per user and per machine.
When would you choose to use un-named shared memory in windows?
it seems to me that message passing between threads is not very useful. One can instead pass a pointer to a struct/variable to the worker threads, and use that as shared memory instead, rather than calling the CreateFileMapping system call.
One reason to use unnamed shared memory is to restrict access to the file mapping to only those processes who are given a handle to it by the creating process. This avoid two problems:
any process that knows the name and has sufficient access to create a mapped file can squat on your named object, preventing or interfering with its legitimate use - this allows a denial of service attack.
accidental rather than malicious name clashes.
When you don't use a name, you can be sure that only processes that you want to have access, get it. From the MSDN docs for CreateFileMapping:
A single file mapping object can be
shared by multiple processes through
inheriting the handle at process
creation, duplicating the handle, or
opening the file mapping object by
name.
Section objects (aka "file mapping objects") are not just used to share memory between processes. The most obvious use of section objects is to map in a file to do I/O, and giving the objects names wouldn't be very useful in most cases. For unnamed pagefile-backed sections ("shared memory") you can still make child processes inherit the handle so they can use the sections.
You can pass handles to unnamed objects across process boundaries. That is to say, you can actually create an unnamed memory map in your application, and access it from another without using a name!
Look at the DuplicateHandle call, which can be used to pass handles to unnamed objects across process boundaries.