Solved

Shared Memory

Posted on 1998-09-23
10
486 Views
Last Modified: 2012-06-27
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
0
Comment
Question by:SkyWolf
  • 3
  • 3
  • 2
  • +2
10 Comments
 
LVL 1

Expert Comment

by:msa092298
ID: 1173513
Do you mean shared memory between processes or between threads? On which platform?   As for NT/95 : between processes you will need using pipes or memory mapped files.  Between threads in the same process, you can do this of course.  But you may need critical sections to avoid concurrent writing to the same location since it may cause problems.
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(&myGlobalLock);
and call this after you no longer need the shared memory and after all threads have exited at the end of your program:
DeleteCriticalSection(&myGlobalLock);

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.
0
 

Author Comment

by:SkyWolf
ID: 1173514
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 ...:)
0
 
LVL 4

Expert Comment

by:agreen
ID: 1173515
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.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1173516
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.
0
 
LVL 1

Expert Comment

by:msa092298
ID: 1173517
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.
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 2

Expert Comment

by:gysbert1
ID: 1173518
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.
0
 

Author Comment

by:SkyWolf
ID: 1173519
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(DB_TYPE));
    memset((queue+line),'\0',sizeof(DB_TYPE));
    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",rmsg.retcode);
    else
    return -5;
    if (cols != NULL)
    sprintf(cols,"%02d",rmsg.cols);
    else
    return -6;
    if (rows != NULL)
    sprintf(rows,"%02d",rmsg.rows);
    else
    return -7;
    return 1;
    }
    i++;
    Sleep(500);
    }
    memset((queue+line),'\0',sizeof(DB_TYPE));
    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,server,ssql,rsql,retcode,cols,rows,strlen(ssql),MAX_SIZE);
    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,server->u.value,ssql->u.ptr,
    rsql->u.ptr,retcode->u.ptr,cols->u.ptr,rows->u.ptr,
    ssql->length,rsql->length);
    if (r == 1)
    {
    LeaveQueue();
    return 1;
    }
    else
    {
    LeaveQueue();
    return r;
    }
    }
0
 

Author Comment

by:SkyWolf
ID: 1173520
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.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1173521
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.  
0
 
LVL 1

Accepted Solution

by:
msa092298 earned 170 total points
ID: 1173522
You will have a lot or concurrency bugs!   You see, 2 or more threads (or processes) may try to write at the same position at the same time, you cannot know exactly which will write first and the data might end up in a mixture of the 2 or more messages.  This depends on when the OS will switch between them.
It seems you are using threads, i.e. all your code resides in the same exe or dll or in different dlls loaded by the same application.  This makes the memory shared by all the DLLs and the exe.   All you need here is a linked list of messages with a critical section which controls concurrency when adding to the end of the list or removing from the top of it.
Yo will need to define a structure for your data that contains the data to post in the message list and a pointer to next member in the list (needed by the following code).
assuming this is your global data include the following code once in one of your files:
==================================================
// the following not needed to be global as long as
// it is in the same file.
static CRITICAL_SECTION c1;  
static void Lock1() {EnterCriticalSection(&c1);}  
static void UnLock1() {LeaveCriticalSection(&c1);}
MyDataType *head;
MyDataType *tail;

static class initializer
{
  public:
  initializer()
  {
    InitializeCriticalSection(&c1);
    head=NULL;
    tail=NULL;
  }
  ~initializer()
  {
     Lock1();UnLock1(); // ensure that none is waiting for it.
     DeleteCriticalSection(&c1);
  }
} theInitializer; // the only object of this type.
 //assuming appending at tail and removing at head
 //now whenever you want to add
void AddToList (MyDataType *data)  // must be global
{
   data->next=NULL;
   Lock1();  // only this thread can change the list
   // can safely and quickly access the shared data.
   if (tail)
     tail->next=data;
   else
     head=data;  // this is the first entry in the list
   tail=data;
   Unlock1(); // other threads can access the shared data safely.
}
MyDataType *RemoveFromList() // must be global
{
   // returns NULL if the list is empty
   MyDataType *data;
   Lock1();
   // can safely and quickly access the shared data.
   *data=head; // whether NULL or not.
   if (head)
   {
      head=head->next;  // may become NULL if the last item
      if (!head)  // the last one in the list
         tail=NULL;
   }
   UnLock1();  // other threads can now access it.
   return data;
}
==================================================

0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now