SkyWolf
asked on
Shared Memory
Can anyone provide me detailed information on the topic shared memory or how to create shared memory in C++ asap ?
Is it correct to say that share memory allows concurrent access to the memory location ? If not, pls show proof to stake your claims .... thanx
Is it correct to say that share memory allows concurrent access to the memory location ? If not, pls show proof to stake your claims .... thanx
ASKER
MSA,
i have to reject ur answer 1st else i think u cannot add ur comments, which i hope u will still be around.
1st, my platform is 32bit application....shared memory as in , the piece of C++ codes will receives multiple request, put them into memory locations.I think the purpose is to avoid error due to concurrent access of memory location. so actually i do not know whether they are threads or processes ....i dun tink it's process ....they r juz messages stored temporary in the memory location, waiting to be retrieve to be process ....
I shall try ur coding method 1st, so do stay around so tat i can give u the pts ...:)
i have to reject ur answer 1st else i think u cannot add ur comments, which i hope u will still be around.
1st, my platform is 32bit application....shared memory as in , the piece of C++ codes will receives multiple request, put them into memory locations.I think the purpose is to avoid error due to concurrent access of memory location. so actually i do not know whether they are threads or processes ....i dun tink it's process ....they r juz messages stored temporary in the memory location, waiting to be retrieve to be process ....
I shall try ur coding method 1st, so do stay around so tat i can give u the pts ...:)
Use the CreateFileMapping() function to create a segment of memory that may be mapped into more than one process.
The first process uses CreateFileMaping() to get a handle to the file. It specifies a name for the file mapping object in the last parameter. The second process uses OpenFileMapping() and specifies the name of the file mapping object the first process created. Then the two processes use the handle in the MapViewOfFile() function to map the file into their memory spaces.
The first process uses CreateFileMaping() to get a handle to the file. It specifies a name for the file mapping object in the last parameter. The second process uses OpenFileMapping() and specifies the name of the file mapping object the first process created. Then the two processes use the handle in the MapViewOfFile() function to map the file into their memory spaces.
SkyWolf, you do not have to reject an answer when you just want the expert to give more information. When th question is locked, the expert can still add comments to the question, as can you. In fact in most cases, an expert will answer a question and a "dialog" between the expert and the client will start until the problem is completely solved.
Supposing you are running under windows (you didn't mention the platform).
If you are running a dll that will be run from a service (eg. ISAPI extension DLL) then all the dlls under that service share the same memory locations and file handles. Your callback functions are called from different threads but inside the same process (or application). If you service the request through web CGIs then they are run in different processes so they cannot share the memory, only the code. Inside threads, you can share memory easily using critical sections. Don't ever forget to free the critical section (LeaveCriticalSection) before leaving the thread, otherwise other threads will be blocked forever. Also, only the thread that entered the critical section can leave it. Initialize the critical section and shared data once in the startup of your code, and DeleteCriticalSection after all threads have done their work and before the whole dll is removed from memory.
How?
I usually define a single object from a hidden class in my DLL, the constructor of that object initializes all the data and all the critical sections. The destructor destroys the global static data and the global critical sections.
e.g.
static CRITICAL_SECTION c1;
void Lock1() {EnterCriticalSection(&c1) ;}
void UnLock1() {LeaveCriticalSection(&c1) ;}
static CRITICAL_SECTION c2;
void Lock2() {EnterCriticalSection(&c2) ;}
void UnLock2() {LeaveCriticalSection(&c2) ;}
static CRITICAL_SECTION c3;
void Lock3() {EnterCriticalSection(&c3) ;}
void UnLock3() {LeaveCriticalSection(&c3) ;}
static MyDataType *mySharedData;
class initializer
{
public:
initializer()
{
InitializeCriticalSection( &c1);
InitializeCriticalSection( &c2);
InitializeCriticalSection( &c3);
mySharedData=new MyDataType();
}
~initializer()
{
Lock1();UnLock1(); // ensure that none is waiting for it.
Lock2();UnLock2(); // ensure that none is waiting for it.
Lock3();UnLock3(); // ensure that none is waiting for it.
DeleteCriticalSection(&c1) ;
DeleteCriticalSection(&c2) ;
DeleteCriticalSection(&c3) ;
delete mySharedData;
mySharedData=NULL; // safeguard against using freed memory.
}
} theInitializer; // the only object of this type.
If you are running a dll that will be run from a service (eg. ISAPI extension DLL) then all the dlls under that service share the same memory locations and file handles. Your callback functions are called from different threads but inside the same process (or application). If you service the request through web CGIs then they are run in different processes so they cannot share the memory, only the code. Inside threads, you can share memory easily using critical sections. Don't ever forget to free the critical section (LeaveCriticalSection) before leaving the thread, otherwise other threads will be blocked forever. Also, only the thread that entered the critical section can leave it. Initialize the critical section and shared data once in the startup of your code, and DeleteCriticalSection after all threads have done their work and before the whole dll is removed from memory.
How?
I usually define a single object from a hidden class in my DLL, the constructor of that object initializes all the data and all the critical sections. The destructor destroys the global static data and the global critical sections.
e.g.
static CRITICAL_SECTION c1;
void Lock1() {EnterCriticalSection(&c1)
void UnLock1() {LeaveCriticalSection(&c1)
static CRITICAL_SECTION c2;
void Lock2() {EnterCriticalSection(&c2)
void UnLock2() {LeaveCriticalSection(&c2)
static CRITICAL_SECTION c3;
void Lock3() {EnterCriticalSection(&c3)
void UnLock3() {LeaveCriticalSection(&c3)
static MyDataType *mySharedData;
class initializer
{
public:
initializer()
{
InitializeCriticalSection(
InitializeCriticalSection(
InitializeCriticalSection(
mySharedData=new MyDataType();
}
~initializer()
{
Lock1();UnLock1(); // ensure that none is waiting for it.
Lock2();UnLock2(); // ensure that none is waiting for it.
Lock3();UnLock3(); // ensure that none is waiting for it.
DeleteCriticalSection(&c1)
DeleteCriticalSection(&c2)
DeleteCriticalSection(&c3)
delete mySharedData;
mySharedData=NULL; // safeguard against using freed memory.
}
} theInitializer; // the only object of this type.
agreen, sorry but I cannot see how your answer is any different from that of msa. I think that msa's answer is closer to the solution here and I would reject yours.
The question here would be how many different programs can access the memory and will they be on the same machine (and thus the same platform).
If you were using threads, beleive me you would know it !
If you say the messages get put in a temporary location for later retreival, how is this done, does the same application that generates the messages read them in again ?
If you use threads you do not need shared memory since the memory space is shared between threads. You would have to use a critical section to PREVENT concurrent access. This pauses the one thread until the other releases the critical section for use.
If you do not the only reason for shared memory would be if you have more than one process (or application) that needs to share the memory. In this case you would also need to use semaphores in order to allow concurrent access.
If none of the above apply the only reason to use any of the above would be because of interrupted processing. In this case an interrupt could cause one function to interrupt the other while it is modifying the data. This is a common scenario when using timers. In this case you cannot use a critical section or shared memory (as me if you cannot figure out why !)
Memory mapped files as mentioned by msa are another method for inter process (application) communication and falls in the shared memory case.
Shared memory is handled using shmget and related functions. If you still need info on that we can talk.
The question here would be how many different programs can access the memory and will they be on the same machine (and thus the same platform).
If you were using threads, beleive me you would know it !
If you say the messages get put in a temporary location for later retreival, how is this done, does the same application that generates the messages read them in again ?
If you use threads you do not need shared memory since the memory space is shared between threads. You would have to use a critical section to PREVENT concurrent access. This pauses the one thread until the other releases the critical section for use.
If you do not the only reason for shared memory would be if you have more than one process (or application) that needs to share the memory. In this case you would also need to use semaphores in order to allow concurrent access.
If none of the above apply the only reason to use any of the above would be because of interrupted processing. In this case an interrupt could cause one function to interrupt the other while it is modifying the data. This is a common scenario when using timers. In this case you cannot use a critical section or shared memory (as me if you cannot figure out why !)
Memory mapped files as mentioned by msa are another method for inter process (application) communication and falls in the shared memory case.
Shared memory is handled using shmget and related functions. If you still need info on that we can talk.
ASKER
ok, everyone be bear with me , bcoz right now i cannot get the codes to run due to some missing *.h files ... some declarations are missing , and the guy who knows where the files are is not available ... i shall post the codes here ...
#include <stdio.h>
#include "direcsql.h"
int EnterQueue(int line,int server, char *s, char *r,
char *retcode,char *cols,char *rows,IQSIZE_T length, IQSIZE_T rlen)
{
//This function put the message onto the message queue that is shared.
BOOL fInit;
DB_TYPE smsg, rmsg;
int i=0;
if (line == 0)
return -1;
else
line = (line*2) -2;
hSharedQ = CreateFileMapping((HANDLE) 0xFFFFFFFF ,
NULL,
PAGE_READWRITE,
0,
SHMEMSIZE,
QUEUE_NAME);
fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
if (hSharedQ == NULL)
{//Cannot allocate memory
return -2;
}
else
{
queue = (DB_TYPE *)MapViewOfFile(hSharedQ,
FILE_MAP_ALL_ACCESS,
0,
0,
0);
if (queue == NULL)
return -3;
if (fInit)
{
memset(queue, '\0', SHMEMSIZE);
}
if (length >= MAX_SIZE)
return -6;
smsg.server = server;
memcpy(smsg.msg,s,length);
smsg.msg[length] = '\0';
//Put information to my own slot.
memcpy((queue+line),&smsg, sizeof(DB_ TYPE));
//wait for message return or time out.
while (i < NO_OF_SECS_TO_WAIT*2)
{
if (*(queue+line+1)->msg != '\0')
{
memcpy(&rmsg,(queue+line+1 ),sizeof(D B_TYPE));
memset((queue+line),'\0',s izeof(DB_T YPE));
memset((queue+line+1),'\0' ,sizeof(DB _TYPE));
if (r != NULL)
{
memcpy(r,rmsg.msg,rlen-1);
r[rlen-1] = '\0';
}
else
return -4;
if (retcode != NULL)
sprintf(retcode,"%02d",rms g.retcode) ;
else
return -5;
if (cols != NULL)
sprintf(cols,"%02d",rmsg.c ols);
else
return -6;
if (rows != NULL)
sprintf(rows,"%02d",rmsg.r ows);
else
return -7;
return 1;
}
i++;
Sleep(500);
}
memset((queue+line),'\0',s izeof(DB_T YPE));
memset((queue+line+1),'\0' ,sizeof(DB _TYPE));
return -8;
}
return -9;
}
BOOL LeaveQueue()
{
//This function is called to remove the DLL from the share memory.
if (queue != NULL)
UnmapViewOfFile(queue);
if (hSharedQ != NULL)
CloseHandle(hSharedQ);
return TRUE;
}
UDLLENTRYEXP ExecSQL(int identity,int server, char *ssql, char *rsql,
char *retcode,char *cols,char *rows)
{
int r;
//This is the function called by the external program to do sending.
if (identity > 96)
identity = 96;
r=EnterQueue(identity,serv er,ssql,rs ql,retcode ,cols,rows ,strlen(ss ql),MAX_SI ZE);
if (r == 1)
{
LeaveQueue();
return 1;
}
else
{
LeaveQueue();
return r;
}
}
UDLLENTRYEXP ExeDirectSQL(IQVAL identity,PUSERDLLPARAM32 server,
PUSERDLLPARAM32 ssql, PUSERDLLPARAM32 rsql,
PUSERDLLPARAM32 retcode,PUSERDLLPARAM32 cols,
PUSERDLLPARAM32 rows)
{
int r;
identity++;
if (identity > 96)
identity = 96;
//This is the function called by the external program to do sending.
r=EnterQueue(identity,serv er->u.valu e,ssql->u. ptr,
rsql->u.ptr,retcode->u.ptr ,cols->u.p tr,rows->u .ptr,
ssql->length,rsql->length) ;
if (r == 1)
{
LeaveQueue();
return 1;
}
else
{
LeaveQueue();
return r;
}
}
#include <stdio.h>
#include "direcsql.h"
int EnterQueue(int line,int server, char *s, char *r,
char *retcode,char *cols,char *rows,IQSIZE_T length, IQSIZE_T rlen)
{
//This function put the message onto the message queue that is shared.
BOOL fInit;
DB_TYPE smsg, rmsg;
int i=0;
if (line == 0)
return -1;
else
line = (line*2) -2;
hSharedQ = CreateFileMapping((HANDLE)
NULL,
PAGE_READWRITE,
0,
SHMEMSIZE,
QUEUE_NAME);
fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
if (hSharedQ == NULL)
{//Cannot allocate memory
return -2;
}
else
{
queue = (DB_TYPE *)MapViewOfFile(hSharedQ,
FILE_MAP_ALL_ACCESS,
0,
0,
0);
if (queue == NULL)
return -3;
if (fInit)
{
memset(queue, '\0', SHMEMSIZE);
}
if (length >= MAX_SIZE)
return -6;
smsg.server = server;
memcpy(smsg.msg,s,length);
smsg.msg[length] = '\0';
//Put information to my own slot.
memcpy((queue+line),&smsg,
//wait for message return or time out.
while (i < NO_OF_SECS_TO_WAIT*2)
{
if (*(queue+line+1)->msg != '\0')
{
memcpy(&rmsg,(queue+line+1
memset((queue+line),'\0',s
memset((queue+line+1),'\0'
if (r != NULL)
{
memcpy(r,rmsg.msg,rlen-1);
r[rlen-1] = '\0';
}
else
return -4;
if (retcode != NULL)
sprintf(retcode,"%02d",rms
else
return -5;
if (cols != NULL)
sprintf(cols,"%02d",rmsg.c
else
return -6;
if (rows != NULL)
sprintf(rows,"%02d",rmsg.r
else
return -7;
return 1;
}
i++;
Sleep(500);
}
memset((queue+line),'\0',s
memset((queue+line+1),'\0'
return -8;
}
return -9;
}
BOOL LeaveQueue()
{
//This function is called to remove the DLL from the share memory.
if (queue != NULL)
UnmapViewOfFile(queue);
if (hSharedQ != NULL)
CloseHandle(hSharedQ);
return TRUE;
}
UDLLENTRYEXP ExecSQL(int identity,int server, char *ssql, char *rsql,
char *retcode,char *cols,char *rows)
{
int r;
//This is the function called by the external program to do sending.
if (identity > 96)
identity = 96;
r=EnterQueue(identity,serv
if (r == 1)
{
LeaveQueue();
return 1;
}
else
{
LeaveQueue();
return r;
}
}
UDLLENTRYEXP ExeDirectSQL(IQVAL identity,PUSERDLLPARAM32 server,
PUSERDLLPARAM32 ssql, PUSERDLLPARAM32 rsql,
PUSERDLLPARAM32 retcode,PUSERDLLPARAM32 cols,
PUSERDLLPARAM32 rows)
{
int r;
identity++;
if (identity > 96)
identity = 96;
//This is the function called by the external program to do sending.
r=EnterQueue(identity,serv
rsql->u.ptr,retcode->u.ptr
ssql->length,rsql->length)
if (r == 1)
{
LeaveQueue();
return 1;
}
else
{
LeaveQueue();
return r;
}
}
ASKER
hi agreen,
as u can see, the piece of code which i have just posted contains the CreateFileMapping and MapViewOfFile.
hi all,
i tink i did not make myself clear during the last comment. :) i am really not aware that i do not have to reject MSA's answer to comment ...and that this code cannot be compiled due to some missing declarations or something therefore i cannot make changes to this code.
as u can see, the piece of code which i have just posted contains the CreateFileMapping and MapViewOfFile.
hi all,
i tink i did not make myself clear during the last comment. :) i am really not aware that i do not have to reject MSA's answer to comment ...and that this code cannot be compiled due to some missing declarations or something therefore i cannot make changes to this code.
skywolf, in order to comment just leave the grades blank, that is, don't mark reject or one of the grades, and type a new comment in the comment box, then press submit.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Define a global variable in your program like this:
CRITICAL_SECTION myGlobalLock;
then call this code once from the main part before using the shared memory : InitializeCriticalSection(
and call this after you no longer need the shared memory and after all threads have exited at the end of your program:
DeleteCriticalSection(&myG
Inside each thread, to access the shared memory you will need:
EnterCriticalSection (&myGlobalLock);
... do your code here (and do not return without executing the following line)
LeaveCriticalSection (&myGlobalLock);
Hope this helps.