DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Unix Shared Memory

09.11.2006
| 9238 views |
  • submit to reddit
        If you want to use multiple blocks of shared memory in a single process
you might need to pass a different id to ftok() for each one.  In any case,
the main entry point is open_shm().  It returns a block of shared memory
of the specified size.  If justreading is 1, then you access what has been
written to that block of shared mem.  If it's 0, then you create a new one
with undefined contents.

PDIE is left as an exercise to the reader...

/* This code written by Nick Welch <mack@incise.org>, 2006.
 *
 * This code is in the public domain
 * and is provided AS IS, with NO WARRANTY. */

static key_t get_shm_key(void)
{
    /* both arbitrary */
    const char * KEY_PATH = "/dev/null";
    const char KEY_ID = 0xc4; 

    key_t key = ftok(KEY_PATH, KEY_ID);
    if (key == (key_t)-1)
        PDIE("ftok");

    return key;
}

static int get_shm_min(void)
{
    struct shminfo info;
    if((shmctl(0, IPC_INFO, (struct shmid_ds *)(void *)&info)) == -1)
        PDIE("shmctl (shminfo)");
    return info.shmmin;
}

static void * open_shm(size_t bytes, int justreading)
{
    void * shm;
    key_t key = get_shm_key();

    int id; 

    if(!justreading)
    {
        /* we need to delete it in case we need to allocate more memory this
         * time than last time.  if we try that without first deleting it, we
         * will get EINVAL.
         */

        id = shmget(key, get_shm_min(), 0644|IPC_CREAT);

        if(id == -1)
            PDIE("shmget (first call)");

        shm = shmat(id, NULL, 0);
        if (shm == NULL)
            PDIE("shmat(first call)");

        if(shmctl(id, IPC_RMID, NULL) == -1)
            PDIE("shmctl (marking shm segment for removal)");

        if(shmdt(shm) == -1)
            PDIE("shmdt (detaching shm segment to delete it)");
    }

    id = shmget(key, bytes, justreading ? 0 : 0644|IPC_CREAT);
    if(id == -1)
        PDIE("shmget (second call)");

    shm = shmat(id, NULL, 0);
    if (shm == NULL)
        PDIE("shmat (second call)");

    return shm;
}