SHARED MEMORY

Shared Memory is an efficient way to pass data between programs. One program creates a shared memory that can be accessed by other processes.

A process creates a shared memory segment using shmget().

The original owner of a shared memory segment can assign ownership to another user with shmctl(). It can also revoke this assignment.

Other processes with proper permission can perform various control functions on the shared memory segment using shmctl().

Once created, a shared segment can be attached to a process address space using shmat(). 

It can be detached using shmdt().

Once attached, the process can read or write to the segment, as allowed by the permission requested in the attach operation. 

A shared memory segment is described by a control structure with a unique ID that points to an area of physical memory. The identifier of the segment is called the shmid. 

The structure definition for the shared memory segment control structures and prototypews can be found in <sys/shm.h>.

In the following few lines you'll find the source code to implement a client server architecture based on a shared memory.

/*@******************************************************

 * INCLUDE SECTION

 ********************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/stat.h>

#include <sys/ipc.h>

#include <sys/shm.h>

 

#define KEY_NUMBER    5000

#define SHMSIZE       8192

int main(int argc, char **argv);

 

int main(int argc, char **argv)

{

    int                         shmid, key;

    char                        *s, *shm;

    

    /* The name for the shared memory */

    key = KEY_NUMBER;

    

    /* Create the shared memory.      */

    if ((shmid = shmget(key, SHMSIZE, IPC_CREAT | 0666)) < 0)

    {

        perror("shmget");

        exit(EXIT_FAILURE);

    }

    

    /* Attach to the shared memory.   */

shm = shmat(shmid, NULL, 0);

    if (shm==NULL)

    {

        perror("shmat");

        exit(EXIT_FAILURE);

    }

    

    /* Fill the shared memory.        */

    s = shm;

    

    

    memset(s, 70, SHMSIZE);

    s[SHMSIZE-1] = '\0';

    

    /* Finally, we wait until the other process

     * changes the first character    */

    while ((char )*shm != '*')

        sleep(1);

    

    exit(EXIT_SUCCESS);

}

And, now, the client

/*

 * shm-client – client program to demonstrate shared memory.

 */

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/shm.h>

 

#define SHMSZ      8192

#define KEY_NUMBER 5000

int main(int argc, char **argv)

{

    int                         shmid;

    key_t                       key;

    char                        *shm, *s;

  

    /* The name for the shared memory. */

    key = 5678;

 

    /* Locate the shared memory.     */

    if ((shmid = shmget(key, SHMSZ, 0666)) < 0)

    {

        perror("shmget");

        exit(1);

    }

 

    /* Attach to the shared memory. */

shm = shmat(shmid, NULL, 0);

    if (shm==NULL)

    {

            perror("shmat");

            exit(1);

    }

    /* Now read what the server put in the memory.  */

    for (s = shm; *s != '\0'; s++)

        putchar(*s);

    putchar('\n');

 

    /* Finally, change the first character of the

     * segment to '*', indicating we have read

     * the segment.    */

    *shm = '*';

 

    exit(0);

}

Last, but not least, the Makefile

ALL_TARGETS=shmem_client shmem_server

CFLAGS=-Wall -pedantic

 

all: $(ALL_TARGETS)

 

shmem_client: shmem_client.o

$(CC) -o shmem_client shmem_client.o

 

shmem_server: shmem_server.o

$(CC) -o shmem_server shmem_server.o

 

shmem_server.o:

 

shmem_server.o:

 

clean:

rm -f $(ALL_TARGETS)

rm -f *.o

 

light:

strip $(ALL_TARGETS)

 

clobber: clean

rm -f core*

This code has been tested on Mac OS X 10.6.8, but it should work fine on most of UNIX dialects.

 

Gg1