I am trying to follow this tutorial on MSDN: Creating Named Shared Memory.
Unfortunately, I get NULL from CreateFileMapping(). The file shmfile.txt exists on my file system, so I thought no problems should occur, the mapping would be created, and the file would take its role as my shared memory object.
What am I doing wrong?
This is my code:
...
#define BUF_SIZE 256
TCHAR szName[]=TEXT("C:\\Users\\joe\\shmfolder\\shmfile.txt");
int main(){
HANDLE hMapFile; // filehandle
LPCTSTR pBuf;
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"), GetLastError());
return 1;
}
...
}
Right now, you're telling CreateFileMapping to create the mapping in the page file, then use the name of your existing file as the name of the file mapping.
The name you give for a file mapping object can have local\ or global\ as a prefix, but can't contain any other back-slashes.
If you want to map your pre-existing file as a shared memory region, you'd do something on this general order:
TCHAR szName[]=TEXT("C:\\Users\\joe\\shmfolder\\shmfile.txt");
TCHAR szMapName[]=TEXT("SharedFile");
HANDLE file = CreateFile(szName, ...);
HANDLE mapping = CreateFileMapping(file, ..., szMapName);
Related
I want to use shared memory to transfer large images (10M or more) between two processes, but I can only request 4096 bytes of BUF_SIZE when requesting shared memory.beyond 4096 bytes, the program will crash.
Here is my code:
hMapFile = CreateFileMappingW(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)超过4096就不行了,不知道怎么解决
szMapName);
My system is windos64, Use C++ in qt.anyone have the same problem as me?
I think I know why the program crashed. It's because there's something wrong with the code below.
hMapFile = CreateFileMappingW(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szMapName); // name of mapping object
if (hMapFile == NULL){
qDebug() << (TEXT("Could not create file mapping object (%d).\n"),GetLastError());
return -1;
}
pBuf = (LPTSTR)MapViewOfFile(
hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
4097);//if this number > 4096, the program will stuck
if (pBuf == NULL){
qDebug() << (TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return -1;
}
You called CreateFileMappingW with BUF_SIZE as the low order DWORD size (with the high order DWORD being 0, so BUF_SIZE is the total number of bytes). That's the limit on what you can map later with MapViewOfFile. I'm guessing you defined BUF_SIZE as a constant 4096 somewhere, so that's the limit on what MapViewOfFile can map. Use a larger number for CreateFileMappingW and MapViewOfFile can increase to match.
I need a mechanism to share memory between some threads (usually in the same process, but sometimes not).
This code, which seems very basic, fails with error 5 (access denied) on MapViewOfFile:
HANDLE hSharedMemCreated = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
10000, // maximum object size (low-order DWORD)
"testFileMapping"); // name of mapping object
HANDLE hSharedMemOpened = OpenFileMapping(
PAGE_READWRITE, // read/write access
FALSE,
"testFileMapping"
);
void* location = MapViewOfFile(
hSharedMemOpened, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
10);
MapViewOfFile succeeds with the opened handle hSharedMemOpened with permission FILE_MAP_READ.
MapViewOfFile succeeds with the created handle hSharedMemCreated with permission FILE_MAP_ALL_ACCESS.
MapViewOfFile fails with the opened handle hSharedMemOpened with permission FILE_MAP_ALL_ACCESS.
The answer is in the comments:
PAGE_READWRITE is not a valid argument for OpenFileMapping(). You probably want FILE_MAP_ALL_ACCESS instead.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
this program is supposed to write to shared memory using win32 API. it is a program given as it is in text book but when i try to execute it it fails. it crashes as i click on execute
the program is supposed to write a string to shared memory
#include<windows.h>
#include<stdio.h>
int main(int argc, char *argv[])
{
HANDLE hFile, hMapFile;
LPVOID lpMapAddress;
//mapping of memory
hFile=CreateFile("temp.txt",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0,0, TEXT("SharedObject"));
lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
//writing into shared memory
sprintf((char*)lpMapAddress,"shared memory writing");
UnmapViewOfFile(lpMapAddress);
CloseHandle(hFile);
CloseHandle(hMapFile);
}
the reason it is crashing is because the file must be created with GENERIC_READ and GENERIC_WRITE access rights since in the CreateFileMapping() function your code specifies PAGE_READWRITE as its third argument(flProtect). This is from MSDN documentation of CreateFileMapping:
The file must be opened with access rights that are compatible with
the protection flags that the flProtect parameter specifies
PAGE_READWRITE=>Gives read/write access to a specific region of pages.
The file that hFile specifies must be created with the GENERIC_READ
and GENERIC_WRITE access rights.
so change
hFile=CreateFile("temp.txt",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);
to
hFile=CreateFile("temp.txt",GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);
One more thing you can not map a file with a size of zero. Here is from MSDN documentation of CreateFileMapping() function:
If this parameter(dwMaximumSizeLow) and dwMaximumSizeHigh are 0 (zero), the maximum size
of the file mapping object is equal to the current size of the file
that hFile identifies.
An attempt to map a file with a length of 0 (zero) fails with an error
code of ERROR_FILE_INVALID. Applications should test for files with a
length of 0 (zero) and reject those files.
If an application specifies a size for the file mapping object that is
larger than the size of the actual named file on disk, the file on
disk is increased to match the specified size of the file mapping
object.
so in your case since the file you are trying to map has initially a size of 0, the CreateFileMapping() function will fail unless you specify the size of a file mapping object in the dwMaximumSizeLow/dwMaximumSizeHigh parameters of CreateFileMapping(). You could do something like this...
HANDLE hFile, hMapFile;
LPVOID lpMapAddress;
//mapping of memory
hFile=CreateFile(L"temp.txt",GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
char* str="shared data to be written";//the data you want to write to the file
int strLen=::strlen(str);//get the string length of the data you want to write
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0,strLen, TEXT("SharedObject")); //here you also specify the size of the mapping object to be equal to the size of data you want to write
if (hMapFile != NULL && hMapFile != INVALID_HANDLE_VALUE)
{
lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
//writing into shared memory
if(lpMapAddress!=NULL)
sprintf((char*)lpMapAddress,"%s","shared file write");
else
printf("error");//error message MapViewOfFile() failed
UnmapViewOfFile(lpMapAddress);
CloseHandle(hMapFile);
}
else
printf("error");//error message CreateFileMapping() failed
CloseHandle(hFile);
}
else
printf("error");//error message CreateFile() failed
I'm currently working on a Bomberman game project where there should be a Server, which has a bidimensional matrix, and 1 or more Clients.
The way that I think it should be done is by using shared memory between process, where the clients and "enemies" access to get the information about the Table Map(Matrix) and work with that.
The problem is that I don't know how to map a pointer to my Map object(Matrix) so the other processes can grab that information.
I've got this function from MSDN but I only explain to a string:
//Server.cpp
//object creation (Matrix)
Mapa M(height, width);
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size(high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
**HANDLE hMapFile = &M; // will this work?**
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // <- How can I pass the object here?
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
Please how can I map a pointer to an object or even to an object so the other processes can access?
Regards,
RC
To use a mapping file your server code should look something like the following. Note that I do not check for any errors to keep the posted code simple (always check for errors!).
/* server */
HANDLE hFile;
HANDLE hMapFile;
hFile = CreateFile("test.dat",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
hMapFile = CreateFileMapping(hFile,
NULL,
PAGE_READWRITE,
0,
1024 * 1024,
"test.mapping"); // "mapping file name" of "test.dat"
/* keep server process running and do not close hFile or hMapFile */
And your client should look something like this:
/* client */
HANDLE hMapFile;
char *pFile; // note: you can use any type of pointer here!
hMapFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
FALSE,
"test.mapping"); // same name as within CreateFileMapping(..)
if (hMapFile != NULL)
{
pFile = MapViewOfFile(hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
1024 * 1024);
/* read pFile */
printf(pFile);
/* write pFile */
wsprintf(pFile, "Hallo?"); // <-- writes to test.dat!!
}
As noted before this design will have some drawbacks if used for a server/client architecture. I recommend using a TCP/IP server/client which is no more difficult to implement than named pipes. A good place to start would be Running the Winsock Client and Server Code Sample but there are numerous other examples on the web...
If using TCP/IP your application will look something like this:
/* server */
// create listener socket
// while running
// accept new client(s)
// receive data from clients (if any data was received)
// react on data: (client sent 0x01 -> send matrix, ...)
/* client */
// create socket and connect to server
// send 0x01 command to obtain matrix
// receive response from server (= get matrix)
// do whatever your client does...
Note that the 0x01 is a simple command byte to tell the server what to do. You're completely free on how to tell the server what to do. You can as well implement a string based command interface (e.g. client sends "get_matrix" instead of 0x01)...
I want to make a share memory pool for all the other process to share the data, but after I read about the CreateFileMapping API document, I was confused about that it will need to specify the size of the share memory. I actually want it to be dynamic allocate and free which looks more like a service. Is there some way to do the share memory dynamic using createFileMapping or not?
Creating Named Shared Memory.
First Process
The first process creates the file mapping object by calling the CreateFileMapping function with INVALID_HANDLE_VALUE and a name for the object. By using the PAGE_READWRITE flag, the process has read/write permission to the memory through any file views that are created.
Then the process uses the file mapping object handle that CreateFileMapping returns in a call to MapViewOfFile to create a view of the file in the process address space. The MapViewOfFile function returns a pointer to the file view, pBuf. The process then uses the CopyMemory function to write a string to the view that can be accessed by other processes.
Process 1 code:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
TCHAR szMsg[]=TEXT("Message from first process.");
int _tmain()
{
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
_getch();
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
Second Process
A second process can access the string written to the shared memory by the first process by calling the OpenFileMapping function specifying the same name for the mapping object as the first process. Then it can use the MapViewOfFile function to obtain a pointer to the file view, pBuf. The process can display this string as it would any other string. In this example, the message box displayed contains the message "Message from first process" that was written by the first process.
Process 2 code:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#pragma comment(lib, "user32.lib")
#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
int _tmain()
{
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not open file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
Source : http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx