|
I have a little question regarding this class: could I have a pointer to a file mapped into a application, and retrieve this pointer into another application ?
I shared a CString in shared memory, just like this:
m_MMFile.MapMemory(g_sMMFName, g_sMutexName, strFileName.GetLength());
LPVOID lpData = m_MMFile.Open();
if(NULL != lpData)
strcpy(static_cast<TCHAR*>(lpData), strFileName);
and in other application, I retrieved CString like that:
CMemMapFile MMFile;
if(MMFile.MapExistingMemory(g_sMMFName, NULL, 0))
{
LPVOID lpData = MMFile.Open();
if(NULL != lpData)
{
CString sRet;
strcpy(sRet.GetBuffer(_MAX_PATH), static_cast<TCHAR*>(lpData));
sRet.ReleaseBuffer();
}
MMFile.Close();
and everything goes all right.
My question is, how can I retrieve a pointer to a file into another app ?
I mean, if I write in an app:
m_MMFile.MapFile(strFileName, FALSE, 1, g_sMMFName, g_sMutexName);
how can I retrieve this pointer in other app ?
As far I understand, for shared memory, I use MapMemory/Open/strcpy to setup CString into shared memory, and to retrieve CString I have used MapExistingMemory/Open/strcpy.
To setup a file pointer into shared memory, I have used MapFile ... but to retrieve that file pointer into another app, what should I use ? I have tried MapExistingMemory/Open, but didn't worked ....
can you guide me a little bit ?
Thank you.
|
|
|
|
|
|
|
MSDN says:
When the process does not need access to the file mapping object, it should call the CloseHandle function. When all handles are closed, the system can free the section of the paging file that the object uses.
From the included test project's CDialog1, unlike MapFile, MapMemory/MapExistingMemory is not paired with UnMap.
Is UnMap unnecessary for MapMemory/MapExistingMemory when closing the application?
|
|
|
|
|
The samples apps provided with the code are just that, i.e. samples. In general All Calls to MapMemory or MapExistingMemory or MapFIle should be paired up with UnMap, but if you forget to do it yourself, you can see that the class will automatically call it for you in the destructor.
|
|
|
|
|
1>------ Rebuild All started: Project: testmemmap, Configuration: Release Win32 ------
1>Deleting intermediate and output files for project 'testmemmap', configuration 'Release|Win32'
1>Compiling...
1>StdAfx.cpp
1>Compiling...
1>testmemmap.cpp
1>Memmap.cpp
1>Generating Code...
1>Compiling resources...
1>Linking...
1>Embedding manifest...
1>Project : error PRJ0003 : Error spawning 'cmd.exe'. => How to fix this problem?
1>Build log was saved at "file://c:\Download\memmap\Release\BuildLog.htm"
1>testmemmap - 1 error(s), 0 warning(s)
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
Don't know how to handle this. Plz help.
|
|
|
|
|
I added "C:\WINDOWS\system32" into VC++ Directories and it works now.
Strange thing is that there is $PATH included at the end of the directories list and $PATH definitley shows PATH=%SystemRoot%\system32; and %SystemRoot% is of cource C:\WINDOWS.
|
|
|
|
|
Hi there,
MMFs provide a mechanism to map portions of a file into memory as needed. This means that applications have a way of getting to a small segment of data out of an extremely large file without having to read the entire file into memory first. But I think the CMemMapFile can not take advantage of this since it allows 1 file has only 1 view a time.
Regards,
HQH.
|
|
|
|
|
I am using the CMemMapFile class for communicating between two different applications running on the same PC. I have noticed a strange (and unwanted) issue: The DEBUG build gets a different LPVOID then the RELEASE build -- which makes things not work between these two apps.
I've been testing with one app, and I can run it and then decide if it is the "Client" or the "Server".
The "Server" does the following:
m_pMap = new CMemMapFile();<br />
m_pMap->MapMemory("MyTest", 1024);<br />
LPVOID pData = m_pMap->Open(60000);<br />
TRACE("Address is %x", pData)<br />
m_pMap->Close();
The "Client" does the following:
m_pMap = new CMemMapFile();<br />
m_pMap->MapExistingMemory("MyTest", 0);<br />
LPVOID pData = m_pMap->Open(60000);<br />
TRACE("Address is %x", pData)<br />
m_pMap->Close();
If I run the debug app multiple times, I can start a server and start several clients, and everything works GREAT! (they all use address 0x01080000). If I run the release app multiple times, I can start a server and several clients, and everything works GREAT! (they all use address 0x009f0000).
BUT, If I start a debug app (server with address 0x1080000) and a release app (client with address 0x009f0000), things go bad!
What have I done wrong? Any ideas?
DanB
PS -- Great class (except for this one weird issue)
|
|
|
|
|
I have resolved this issue in my code. Strangely enough, both addresses resolve to the exact same mapped memory, so it DOES work.
Thanks for a great class!
DanB
|
|
|
|
|
Can I use the CMemMapFile for remote file mapping? I mentioned that if I map the file on one station and than update it from the other (with flushing), the view doesn't reflect the changes. But if I unmap the file and map it once more, I see the shanges. Thanks in advance.
|
|
|
|
|
Can someone tell me what's the pupose of DWORD dwBytes parameter in MapMemory ect functions ,even when i give wrong length nothing gets wrong.
Unmanaged in a .NET world
|
|
|
|
|
dwBytes specifies how much shared memory in bytes you want to allocate. Simple as that. There is no "wrong" value to use!, just that bigger values will allocate more virtual memory. It's similiar to the value you would pass to malloc or GlobalAlloc or any memory allocator.
|
|
|
|
|
actually this question came from the fact that when i write some shared memory i definately know the size of data , but when in the other process i read that memory i could not know hom much data other process has written , as data might vary from some bytes to some Mbytes .So what length should i use in MapExistingMemory when reading data.
just for testing i wrote 556 bytes data , by specifying 1 byte as length in MapMeory and while reading i used 1 byte again in MapExistingMemory , and i was able to read the whole data successfully , from there i asked whats the use of it if i specify wrong length still every thing works fine.
So can kindly u tell me how the read whole data , when u dont know that size of shared memory.
Thanx Atif Mushtaq
Unmanaged in a .NET world
|
|
|
|
|
Both programs need to agree between themselves on the size of the shared memory. One method to achieve this would be to put the full size of the MMF at the start of the shared memory, then client programs can determine by initially mapping 4 bytes. The fact that reading one byte worked is due to allocation quantization. If you ask for a certain size it will always be rounded up to an allocation boundary (probably 4K I think).
|
|
|
|
|
I wrote a test case to prove the "growable" option of this class--the only option not verified by the included download.
I find that when I try to write to position 4096 in the file, I get an access violation instead of "silently growing the file." Here is where things go wrong:
mmf.MapFile( csPath, FALSE, 0, FALSE, FALSE, TRUE );
char* pFile = (char*)mmf.Open();
const char szText[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
int nChars = strlen( szText );
int nChar;
int nLen = strlen( pFile ); // initial file length is 3597
int nLine, nLines = 1000;
for ( nLine = 0; nLine < nLines; nLine++ )
{___for ( nChar = 0; nChar < nChars; nChar++ )
____{___pFile[ nLen++ ] = szText[ nChar ]; // fails at nLen == 4096 (paging buffer size)
____}
____pFile[ nLen ] = 0;
}
mmf.Flush();
mmf.Close();
mmf.UnMap();
Has anyone made this work?
"Learn from the mistakes of others. You can't live long enough to make them all yourself." Unknown
|
|
|
|
|
I answered my own question...there is a bug is the code. Under the MapHandle call, the call to ::CreateFileMapping sets the length of the file to dwLength which is equal to the original file length (plus two if automatic null termination is enabled). The documentation states that an error will occur if this length is exceeded.
Since the FSCTL_SET_SPARSE property was set earlier, the file size can be set larger without actually increasing the size on disk...this larger size is the point where an exception occurs.
I verified this with a test.
There should be another parameter to the MapHandle to optionally set an upper limit on the sparse file size.
I do not like having to set an upper limit on the size, has anyone worked out a better method (like detecting an exeption and extending the size)?
"Learn from the mistakes of others. You can't live long enough to make them all yourself." Unknown
|
|
|
|
|
First thing to do is make sure you have the latest version from my web site at www.naughter.com, as I remember making some recent updates to this class in or around this area.
|
|
|
|
|
Thanks, I will do so again (I did check it, but the version number is the same as this one, so I did not download it).
"Learn from the mistakes of others. You can't live long enough to make them all yourself." Unknown
|
|
|
|
|
The latest version on my web site is v1.47.
|
|
|
|
|
I was just about to reply that I mis-read the version number.
Thanks again.
"Learn from the mistakes of others. You can't live long enough to make them all yourself." Unknown
|
|
|
|
|
I did try to use the "growable" option and the "DeviceIoControl" function used to set the file sparse option in the MapFile function always return an error. I am using WinXP, so I should have the appropriate NTFS version. Any clue what the problem could be?
Here is the parameters I'm using:
m_mmf.MapFile(_T("memfile.dat"), FALSE, 0, FALSE, TRUE);
Help would be appreciated.
Thanks.
|
|
|
|
|
Couple of things to make sure:
1. That you have the latest version from my web site.
2. That the file "memfile.dat" is on an NTFS volume. Just because you have XP, may not absolutely guarantee the drive is using NTFS. You can check this by right clicking the drive in Explorer and selecting properties.
3. Use an absolute path in the call to MapFile
4. What exactly was the error code and this might point you in the right direction
|
|
|
|
|
R1. I used the latest version from your web site.
R2. Yes, the file "memfile.dat" is on an NTFS volume.
R3. I tried it with an absolute path and I still have the problem.
R4. The error code is "1". I think it means "invalid function"
I just can't create sparse file and I don't understand why.
Thanks
|
|
|
|
|
Ok, I found the problem. I am using the code on WinXP but I compiled it using VC6 with the original SDK. The latest WinIOCTL.h definition file is quite different from the VC6 version and the FSCTL_SET_SPARSE macro definition is different. With the VC6 WinIOCTL.h, the macro generates the value 0x000980C4, but the correct value for the DeviceIoControl function to enable the sparse file option is 0x000900C4. This is the value I get when I use the FSCTL_SET_SPARSE macro from the latest WinIOCTL.h version.
Thanks for your help.
|
|
|
|