Never been to DZone Snippets before?

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

« Newer Snippets
Older Snippets »
Showing 1-2 of 2 total  RSS 

Unix Shared Memory

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;
}

Simple popen2 implementation

I needed a simple popen2 implementation. This is similar to popen, but allows for bidirectional communication with the application being executed. Based on some other examples, I put this together. It makes for a good base.

#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define READ 0
#define WRITE 1

pid_t
popen2(const char *command, int *infp, int *outfp)
{
    int p_stdin[2], p_stdout[2];
    pid_t pid;

    if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
        return -1;

    pid = fork();

    if (pid < 0)
        return pid;
    else if (pid == 0)
    {
        close(p_stdin[WRITE]);
        dup2(p_stdin[READ], READ);
        close(p_stdout[READ]);
        dup2(p_stdout[WRITE], WRITE);

        execl("/bin/sh", "sh", "-c", command, NULL);
        perror("execl");
        exit(1);
    }

    if (infp == NULL)
        close(p_stdin[WRITE]);
    else
        *infp = p_stdin[WRITE];

    if (outfp == NULL)
        close(p_stdout[READ]);
    else
        *outfp = p_stdout[READ];

    return pid;
}


Simple usage would be:

int
main(int argc, char **argv)
{
    int infp, outfp;
    char buf[128];

    if (popen2("sort", &infp, &outfp) <= 0)
    {
        printf("Unable to exec sort\n");
        exit(1);
    }

    write(infp, "Z\n", 2);
    write(infp, "D\n", 2);
    write(infp, "A\n", 2);
    write(infp, "C\n", 2);
    close(infp);

    *buf = '\0';
    read(outfp, buf, 128);

    printf("buf = '%s'\n", buf);

    return 0;
}
« Newer Snippets
Older Snippets »
Showing 1-2 of 2 total  RSS