Gregory Hildstrom Projects Publications Resume Links Contact About Google+ Facebook Youtube Donate




Linux System V and POSIX IPC Examples

Introduction
System V Private IPC
Shared Memory
Semaphores
Message Queues
Makefile

Introduction

Some recent tasks at work highlighted some obvious gaps in my working knowledge of Linux inter-process communication (IPC). I spent some personal time brushing up on things I had used before and learning about some mechanisms that I had not used before. I am not discussing pipes or sockets here; I am discussing message queues, semaphores, and shared memory. The System V and POSIX specifications have different APIs for using basically the same three IPC mechanisms. I am not exploring every nuance or feature of each API and I am not comparing performance. My goal was simply to demonstrate each IPC mechanism for each API in a set of very simple programs. I show the programs side by side where appropriate, but the code is also available in
ipc_sysv_posix.zip.

The man pages are extremely helpful when diving into stuff like this. Some good starting points are 'man svipc', 'man shm_overview', 'man sem_overview', and 'man mq_overview'. It is important to clean up after yourself. IPC mechanisms tend to persist in the Linux kernel until the next reboot unless they are explicitly removed. See 'man ipcs' for information on listing IPC mechanisms.

My test system runs Fedora 20 Linux with the latest updates as of August 9, 2015. The Makefile at the end shows the compile commands.

System V Private IPC

The System V API allows for private, unnamed, in-memory IPC mechanisms to be shared between parent and identical forked child processes. The processes must be the same and the IPC mechanisms will not be passed along to different exec'd processes. System V IPC among different processes requires a file system path name and a project name to identify a shared IPC resource. So, System V IPC mechanisms can all be named or unnamed. POSIX supports named (sem_open) and unnamed (sem_init) semaphores, but message queues (mq_open) and shared memory (shm_open) must be named. Here I demonstrate private unnamed System V shared memory IPC between a parent process and a forked child process. The same key=IPC_PRIVATE approach also applies to the other System V IPC mechanisms, so I only wrote an example program for private unnamed shared memory.
/*
 * This demonstrates shared memory IPC and child inheritance of
 * attached shared memory segments. Note that the IPC_PRIVATE shmget key is
 * only useful for parent and child forked processes. Different processes
 * must use an explicit key number, usually provided by ftok().
 *
 * This page is a useful supplement to the man pages.
 * http://www.cs.cf.ac.uk/Dave/C/node27.html
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(int argc, char **argv)
{
    int rc = 1;
    pid_t cpid = 0;
    int shmid = 0;
    struct shmid_ds shmbuf;
    char *buffer = NULL;
    size_t buffer_size = 4096;
    int size = 0;
    shmid = shmget(IPC_PRIVATE, buffer_size, IPC_CREAT | 0666);
    if (shmid < 0) {
        perror("shmget");
        goto cleanup;
    }
    buffer = (char*)shmat(shmid, NULL, 0);
    if (buffer < 0) {
        perror("shmat");
        goto cleanup;
    }
    cpid = fork();
    if (cpid < 0) {
        perror("fork");
        goto cleanup;
    }
    else if (cpid == 0) {
        printf("child pid is %d\n", getpid());
        size = snprintf(buffer, buffer_size, "hello from child");
        if (size <= 0) {
            perror("snprintf");
            goto cleanup;
        }
        printf("child wrote to shared memory buffer: %s\n", buffer);
    }
    else {
        printf("parent pid is %d and child pid is %d\n", getpid(), cpid);
        wait(0);
        printf("parent read from shared memory buffer: %s\n", buffer);
    }
    rc = 0;
cleanup:
    if (buffer > 0)
        shmdt(buffer);
    if (shmid > 0)
        shmctl(shmid, IPC_RMID, &shmbuf);
    return rc;
}


Here is the output:
[ghildstrom@hplt ipc_sysv_posix]$ ./sysv_shared_memory_private 
parent pid is 2164 and child pid is 2165
child pid is 2165
child wrote to shared memory buffer: hello from child
parent read from shared memory buffer: hello from child

Shared Memory

listingSystem VPOSIX
parent
source
/*
 * This demonstrates shared memory IPC for separate processes using a file
 * system path reference to shared memory. Note that the shmget key is
 * derived from a path and the child execve's a totally separate process.
 *
 * This page is a useful supplement to the man pages.
 * http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/shm/example-2.html
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(int argc, char **argv)
{
    int rc = 1;
    pid_t cpid = 0;
    key_t key = 0;
    int shmid = 0;
    struct shmid_ds shmbuf;
    char *buffer = NULL;
    size_t buffer_size = 4096;
    int exec = 0;
    key = ftok("shmfile", 'R');
    if (key < 0) {
        perror("ftok");
        goto cleanup;
    }
    shmid = shmget(key, buffer_size, IPC_CREAT | 0666);
    if (shmid < 0) {
        perror("shmget");
        goto cleanup;
    }
    buffer = (char*)shmat(shmid, NULL, 0);
    if (buffer < 0) {
        perror("shmat");
        goto cleanup;
    }
    cpid = fork();
    if (cpid < 0) {
        perror("fork");
        goto cleanup;
    }
    else if (cpid == 0) {
        printf("child pid is %d\n", getpid());
        exec = execve("sysv_shared_memory_file_child", NULL, NULL);
        if (exec < 0) {
            perror("execve");
            goto cleanup;
        }
    }
    else {
        printf("parent pid is %d and child pid is %d\n", getpid(), cpid);
        wait(0);
        printf("parent read from shared memory buffer: %s\n", buffer);
    }
    rc = 0;
cleanup:
    if (buffer > 0)
        shmdt(buffer);
    if (shmid > 0)
        shmctl(shmid, IPC_RMID, &shmbuf);
    return rc;
}

/*
 * This demonstrates POSIX shared memory IPC for separate processes using a
 * name reference to shared memory. Note that the child execve's a totally
 * separate process.
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char **argv)
{
    int rc = 1;
    pid_t cpid = 0;
    int shmfd = 0;
    char *buffer = NULL;
    size_t buffer_size = 4096;
    int exec = 0;
    int rv = 0;
    shmfd = shm_open("/shmname", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
    if (shmfd < 0) {
        perror("shm_open");
        goto cleanup;
    }
    rv = ftruncate(shmfd, buffer_size);
    if (rv < 0) {
        perror("ftruncate");
        goto cleanup;
    }
    buffer = mmap(NULL, buffer_size, PROT_READ, MAP_SHARED, shmfd, 0);
    if (buffer < 0) {
        perror("mmap");
        goto cleanup;
    }
    cpid = fork();
    if (cpid < 0) {
        perror("fork");
        goto cleanup;
    }
    else if (cpid == 0) {
        printf("child pid is %d\n", getpid());
        exec = execve("posix_shared_memory_child", NULL, NULL);
        if (exec < 0) {
            perror("execve");
            goto cleanup;
        }
    }
    else {
        printf("parent pid is %d and child pid is %d\n", getpid(), cpid);
        wait(0);
        printf("parent read from shared memory buffer: %s\n", buffer);
    }
    rc = 0;
cleanup:
    if (buffer > 0)
        munmap(buffer, buffer_size);
    if (shmfd > 0) {
        close(shmfd);
        shm_unlink("/shmname");
    }
    return rc;
}

child
source
/*
 * This demonstrates shared memory IPC for separate processes using a file
 * system path reference to shared memory. Note that the shmget key is
 * derived from a path and this is separate from the initial forked child.
 *
 * This page is a useful supplement to the man pages.
 * http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/shm/example-2.html
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(int argc, char **argv)
{
    int rc = 1;
    key_t key = 0;
    int shmid = 0;
    char *buffer = NULL;
    size_t buffer_size = 4096;
    int size = 0;
    key = ftok("shmfile", 'R');
    if (key < 0) {
        perror("ftok");
        goto cleanup;
    }
    shmid = shmget(key, buffer_size, 0666);
    if (shmid < 0) {
        perror("shmget");
        goto cleanup;
    }
    buffer = (char*)shmat(shmid, NULL, 0);
    if (buffer < 0) {
        perror("shmat");
        goto cleanup;
    }
    printf("execve'd child pid is %d\n", getpid());
    size = snprintf(buffer, buffer_size, "hello from execve'd child");
    if (size <= 0) {
        perror("snprintf");
        goto cleanup;
    }
    printf("execve'd child wrote to shared memory buffer: %s\n", buffer);
    rc = 0;
cleanup:
    if (buffer > 0)
        shmdt(buffer);
    return rc;
}

/*
 * This demonstrates POSIX shared memory IPC for separate processes using a
 * name reference to shared memory. Note that this is separate from the
 * initial forked child.
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char **argv)
{
    int rc = 1;
    int shmfd = 0;
    char *buffer = NULL;
    size_t buffer_size = 4096;
    int size = 0;
    shmfd = shm_open("/shmname", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
    if (shmfd < 0) {
        perror("shm_open");
        goto cleanup;
    }
    buffer = mmap(NULL, buffer_size, PROT_WRITE, MAP_SHARED, shmfd, 0);
    if (buffer < 0) {
        perror("mmap");
        goto cleanup;
    }
    printf("execve'd child pid is %d\n", getpid());
    size = snprintf(buffer, buffer_size, "hello from execve'd child");
    if (size <= 0) {
        perror("snprintf");
        goto cleanup;
    }
    printf("execve'd child wrote to shared memory buffer: %s\n", buffer);
    rc = 0;
cleanup:
    if (buffer > 0)
        munmap(buffer, buffer_size);
    if (shmfd > 0)
        close(shmfd);
    return rc;
}

output
[ghildstrom@hplt ipc_sysv_posix]$ ./sysv_shared_memory_file_parent 
parent pid is 2435 and child pid is 2436
child pid is 2436
execve'd child pid is 2436
execve'd child wrote to shared memory buffer: hello from execve'd child
parent read from shared memory buffer: hello from execve'd child
[ghildstrom@hplt ipc_sysv_posix]$ ./posix_shared_memory_parent 
parent pid is 2476 and child pid is 2477
child pid is 2477
execve'd child pid is 2477
execve'd child wrote to shared memory buffer: hello from execve'd child
parent read from shared memory buffer: hello from execve'd child

Semaphores

listingSystem VPOSIX
parent
source
/*
 * This demonstrates semaphore IPC for separate processes using a file
 * system path reference to a semaphore. Note that the semget key is
 * derived from a path and the child execve's a totally separate process.
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int main(int argc, char **argv)
{
    int rc = 1;
    pid_t cpid = 0;
    key_t key = 0;
    int semid = 0;
    struct sembuf sops[2];
    int rv = 0;
    int exec = 0;
    key = ftok("semfile", 'R');
    if (key < 0) {
        perror("ftok");
        goto cleanup;
    }
    semid = semget(key, 1, IPC_CREAT | 0666);
    if (semid < 0) {
        perror("semget");
        goto cleanup;
    }
    sops[0].sem_num = 0;
    sops[0].sem_op = 1;
    sops[0].sem_flg = 0;
    rv = semop(semid, sops, 1);
    if (rv < 0) {
        perror("semop");
        goto cleanup;
    }
    cpid = fork();
    if (cpid < 0) {
        perror("fork");
        goto cleanup;
    }
    else if (cpid == 0) {
        printf("child pid is %d\n", getpid());
        exec = execve("sysv_semaphore_file_child", NULL, NULL);
        if (exec < 0) {
            perror("execve");
            goto cleanup;
        }
    }
    else {
        printf("parent pid is %d and child pid is %d\n", getpid(), cpid);
        sleep(1);
        printf("parent delay\n");
        sleep(2);
        printf("parent about to decrement semaphore back to zero\n");
        sops[0].sem_op = -1;
        rv = semop(semid, sops, 1);
        if (rv < 0) {
            perror("semop");
            goto cleanup;
        }
        wait(0);
    }
    rc = 0;
cleanup:
    if (semid > 0)
        semctl(semid, 1, IPC_RMID);
    return rc;
}

/*
 * This demonstrates POSIX semaphore IPC for separate processes using a
 * name reference to a semaphore. Note that the child execve's a totally
 * separate process.
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

int main(int argc, char **argv)
{
    int rc = 1;
    pid_t cpid = 0;
    sem_t *sem = NULL;
    int rv = 0;
    int exec = 0;
    sem = sem_open("/semname", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO, 0);
    if (sem == SEM_FAILED) {
        perror("sem_open");
        goto cleanup;
    }
    cpid = fork();
    if (cpid < 0) {
        perror("fork");
        goto cleanup;
    }
    else if (cpid == 0) {
        printf("child pid is %d\n", getpid());
        exec = execve("posix_semaphore_child", NULL, NULL);
        if (exec < 0) {
            perror("execve");
            goto cleanup;
        }
    }
    else {
        printf("parent pid is %d and child pid is %d\n", getpid(), cpid);
        sleep(1);
        printf("parent delay\n");
        sleep(2);
        printf("parent about to increment semaphore to non-zero\n");
        rv = sem_post(sem);
        if (rv < 0) {
            perror("sem_post");
            goto cleanup;
        }
        wait(0);
    }
    rc = 0;
cleanup:
    if (sem != SEM_FAILED) {
        sem_close(sem);
        sem_unlink("/semname");
    }
    return rc;
}

child
source
/*
 * This demonstrates semaphore IPC for separate processes using a file
 * system path reference to a semaphore. Note that the semget key is
 * derived from a path and this is separate from the initial forked child.
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int main(int argc, char **argv)
{
    int rc = 1;
    key_t key = 0;
    int semid = 0;
    struct sembuf sops[2];
    int rv = 0;
    key = ftok("semfile", 'R');
    if (key < 0) {
        perror("ftok");
        goto cleanup;
    }
    semid = semget(key, 1, 0666);
    if (semid < 0) {
        perror("semget");
        goto cleanup;
    }
    printf("execve'd child pid is %d\n", getpid());
    printf("execve'd child waiting for semaphore zero value\n");
    sops[0].sem_num = 0;
    sops[0].sem_op = 0;
    sops[0].sem_flg = 0;
    rv = semop(semid, sops, 1);
    if (rv < 0) {
        perror("semop");
        goto cleanup;
    }
    printf("execve'd child detected semaphore zero value\n");
    rc = 0;
cleanup:
    return rc;
}

/*
 * This demonstrates POSIX semaphore IPC for separate processes using a
 * name reference to a semaphore. Note that this is separate from the
 * initial forked child.
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

int main(int argc, char **argv)
{
    int rc = 1;
    sem_t *sem = NULL;
    int rv = 0;
    sem = sem_open("/semname", O_RDWR);
    if (sem == SEM_FAILED) {
        perror("sem_open");
        goto cleanup;
    }
    printf("execve'd child pid is %d\n", getpid());
    printf("execve'd child waiting for semaphore non-zero value\n");
    rv = sem_wait(sem);
    if (rv < 0) {
        perror("sem_wait");
        goto cleanup;
    }
    printf("execve'd child detected semaphore non-zero value\n");
    rc = 0;
cleanup:
    if (sem != SEM_FAILED)
        sem_close(sem);
    return rc;
}

output
[ghildstrom@hplt ipc_sysv_posix]$ ./sysv_semaphore_file_parent 
parent pid is 2899 and child pid is 2900
child pid is 2900
execve'd child pid is 2900
execve'd child waiting for semaphore zero value
parent delay
parent about to decrement semaphore back to zero
execve'd child detected semaphore zero value
[ghildstrom@hplt ipc_sysv_posix]$ ./posix_semaphore_parent 
parent pid is 2925 and child pid is 2926
child pid is 2926
execve'd child pid is 2926
execve'd child waiting for semaphore non-zero value
parent delay
parent about to increment semaphore to non-zero
execve'd child detected semaphore non-zero value

Message Queues

listingSystem VPOSIX
parent
source
/*
 * This demonstrates message queue IPC for separate processes using a file
 * system path reference to a message queue. Note that the msgget key is
 * derived from a path and the child execve's a totally separate process.
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct msgbuf {
    long mtype;
    char mtext[1];
};

int main(int argc, char **argv)
{
    int rc = 1;
    pid_t cpid = 0;
    key_t key = 0;
    int msgid = 0;
    struct msqid_ds msgds;
    struct msgbuf msg;
    int rv = 0;
    int exec = 0;
    key = ftok("msgfile", 'R');
    if (key < 0) {
        perror("ftok");
        goto cleanup;
    }
    msgid = msgget(key, IPC_CREAT | 0666);
    if (msgid < 0) {
        perror("msgget");
        goto cleanup;
    }
    cpid = fork();
    if (cpid < 0) {
        perror("fork");
        goto cleanup;
    }
    else if (cpid == 0) {
        printf("child pid is %d\n", getpid());
        exec = execve("sysv_message_queue_file_child", NULL, NULL);
        if (exec < 0) {
            perror("execve");
            goto cleanup;
        }
    }
    else {
        printf("parent pid is %d and child pid is %d\n", getpid(), cpid);
        sleep(1);
        printf("parent delay\n");
        sleep(2);
        printf("parent about to send message\n");
        msg.mtype = 1234;
        rv = msgsnd(msgid, &msg, 0, 0);
        if (rv < 0) {
            perror("msgsnd");
            goto cleanup;
        }
        wait(0);
    }
    rc = 0;
cleanup:
    if (msgid > 0)
        msgctl(msgid, IPC_RMID, &msgds);
    return rc;
}

/*
 * This demonstrates POSIX message queue IPC for separate processes using a
 * name reference to a message queue. Note that the child execve's a totally
 * separate process.
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>

int main(int argc, char **argv)
{
    int rc = 1;
    pid_t cpid = 0;
    key_t key = 0;
    mqd_t msgid = 0;
    struct mq_attr attr;
    char *msg = NULL;
    int rv = 0;
    int exec = 0;
    msg = (char*)malloc(1024);
    if (!msg) {
        perror("msg");
        goto cleanup;
    }
    attr.mq_flags = O_RDWR;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = 1024;
    attr.mq_curmsgs = 0;
    msgid = mq_open("/msgname", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO, &attr);
    if (msgid < 0) {
        perror("mq_open");
        goto cleanup;
    }
    cpid = fork();
    if (cpid < 0) {
        perror("fork");
        goto cleanup;
    }
    else if (cpid == 0) {
        printf("child pid is %d\n", getpid());
        exec = execve("posix_message_queue_child", NULL, NULL);
        if (exec < 0) {
            perror("execve");
            goto cleanup;
        }
    }
    else {
        printf("parent pid is %d and child pid is %d\n", getpid(), cpid);
        sleep(1);
        printf("parent delay\n");
        sleep(2);
        printf("parent about to send message\n");
        rv = snprintf(msg, 1024, "1234");
        if (rv <= 0) {
            perror("snprintf");
            goto cleanup;
        }
        rv = mq_send(msgid, msg, strlen(msg), 0);
        if (rv < 0) {
            perror("mq_send");
            goto cleanup;
        }
        wait(0);
    }
    rc = 0;
cleanup:
    if (msgid > 0) {
        mq_close(msgid);
        mq_unlink("/msgname");
    }
    return rc;
}

child
source
/*
 * This demonstrates message queue IPC for separate processes using a file
 * system path reference to a message queue. Note that the msgget key is
 * derived from a path and this is separate from the initial forked child.
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct msgbuf {
    long mtype;
    char mtext[1];
};

int main(int argc, char **argv)
{
    int rc = 1;
    key_t key = 0;
    int msgid = 0;
    struct msgbuf msg;
    ssize_t rv = 0;
    key = ftok("msgfile", 'R');
    if (key < 0) {
        perror("ftok");
        goto cleanup;
    }
    msgid = msgget(key, 0666);
    if (msgid < 0) {
        perror("msgget");
        goto cleanup;
    }
    printf("execve'd child pid is %d\n", getpid());
    printf("execve'd child waiting for message\n");
    rv = msgrcv(msgid, &msg, 0, 0, 0);
    if (rv < 0) {
        perror("msgrcv");
        goto cleanup;
    }
    printf("execve'd child received message type %d\n", msg.mtype);
    rc = 0;
cleanup:
    return rc;
}

/*
 * This demonstrates POSIX message queue IPC for separate processes using a
 * name reference to a message queue. Note that this is separate from the
 * initial forked child.
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>

int main(int argc, char **argv)
{
    int rc = 1;
    key_t key = 0;
    mqd_t msgid = 0;
    char *msg = NULL;
    ssize_t rv = 0;
    msg = (char*)malloc(1024);
    if (!msg) {
        perror("malloc");
        goto cleanup;
    }
    msgid = mq_open("/msgname", O_RDONLY);
    if (msgid < 0) {
        perror("mq_open");
        goto cleanup;
    }
    printf("execve'd child pid is %d\n", getpid());
    printf("execve'd child waiting for message\n");
    rv = mq_receive(msgid, msg, 1024, NULL);
    if (rv < 0) {
        perror("mq_receive");
        goto cleanup;
    }
    printf("execve'd child received message %s\n", msg);
    rc = 0;
cleanup:
    free(msg);
    if (msgid > 0)
        mq_close(msgid);
    return rc;
}

output
[ghildstrom@hplt ipc_sysv_posix]$ ./sysv_message_queue_file_parent 
parent pid is 2965 and child pid is 2966
child pid is 2966
execve'd child pid is 2966
execve'd child waiting for message
parent delay
parent about to send message
execve'd child received message type 1234
[ghildstrom@hplt ipc_sysv_posix]$ ./posix_message_queue_parent 
parent pid is 2992 and child pid is 2993
child pid is 2993
execve'd child pid is 2993
execve'd child waiting for message
parent delay
parent about to send message
execve'd child received message 1234

Makefile

all: sysv posix
clean: sysv_clean posix_clean

sysv: \
sysv_shared_memory_private \
shmfile \
sysv_shared_memory_file_parent \
sysv_shared_memory_file_child \
semfile \
sysv_semaphore_file_parent \
sysv_semaphore_file_child \
msgfile \
sysv_message_queue_file_parent \
sysv_message_queue_file_child

sysv_shared_memory_private: sysv_shared_memory_private.c
	gcc -o sysv_shared_memory_private sysv_shared_memory_private.c

shmfile:
	touch shmfile

sysv_shared_memory_file_parent: sysv_shared_memory_file_parent.c
	gcc -o sysv_shared_memory_file_parent sysv_shared_memory_file_parent.c

sysv_shared_memory_file_child: sysv_shared_memory_file_child.c
	gcc -o sysv_shared_memory_file_child sysv_shared_memory_file_child.c

semfile:
	touch semfile

sysv_semaphore_file_parent: sysv_semaphore_file_parent.c
	gcc -o sysv_semaphore_file_parent sysv_semaphore_file_parent.c

sysv_semaphore_file_child: sysv_semaphore_file_child.c
	gcc -o sysv_semaphore_file_child sysv_semaphore_file_child.c

msgfile:
	touch msgfile

sysv_message_queue_file_parent: sysv_message_queue_file_parent.c
	gcc -o sysv_message_queue_file_parent sysv_message_queue_file_parent.c

sysv_message_queue_file_child: sysv_message_queue_file_child.c
	gcc -o sysv_message_queue_file_child sysv_message_queue_file_child.c

sysv_clean:
	rm -f sysv_shared_memory_private
	rm -f shmfile
	rm -f sysv_shared_memory_file_parent
	rm -f sysv_shared_memory_file_child
	rm -f semfile
	rm -f sysv_semaphore_file_parent
	rm -f sysv_semaphore_file_child
	rm -f msgfile
	rm -f sysv_message_queue_file_parent
	rm -f sysv_message_queue_file_child

posix: \
posix_shared_memory_parent \
posix_shared_memory_child \
posix_semaphore_parent \
posix_semaphore_child \
posix_message_queue_parent \
posix_message_queue_child

posix_shared_memory_parent: posix_shared_memory_parent.c
	gcc -lrt -o posix_shared_memory_parent posix_shared_memory_parent.c

posix_shared_memory_child: posix_shared_memory_child.c
	gcc -lrt -o posix_shared_memory_child posix_shared_memory_child.c

posix_semaphore_parent: posix_semaphore_parent.c
	gcc -pthread -o posix_semaphore_parent posix_semaphore_parent.c

posix_semaphore_child: posix_semaphore_child.c
	gcc -pthread -o posix_semaphore_child posix_semaphore_child.c

posix_message_queue_parent: posix_message_queue_parent.c
	gcc -lrt -o posix_message_queue_parent posix_message_queue_parent.c

posix_message_queue_child: posix_message_queue_child.c
	gcc -lrt -o posix_message_queue_child posix_message_queue_child.c

posix_clean:
	rm -f posix_shared_memory_parent
	rm -f posix_shared_memory_child
	rm -f posix_semaphore_parent
	rm -f posix_semaphore_child
	rm -f posix_message_queue_parent
	rm -f posix_message_queue_child