diff options
| author | Michael Stapelberg <michael@stapelberg.de> | 2010-12-06 19:55:19 +0100 |
|---|---|---|
| committer | Michael Stapelberg <michael@stapelberg.de> | 2010-12-06 19:55:19 +0100 |
| commit | 0c9d712a77bbede4808142944776d35f502bffa7 (patch) | |
| tree | 1955e375d404308aa1d79b9d355e37dba739b9bf /aufgabe4/queue.c | |
| parent | 9af2bea582c083653c08abb965eba6f63de997fa (diff) | |
| download | prozesskommunikation-0c9d712a77bbede4808142944776d35f502bffa7.tar.gz prozesskommunikation-0c9d712a77bbede4808142944776d35f502bffa7.tar.bz2 | |
IPC implementiert
Hat noch einen Bug, sollte aber als Beispiel für die anderen Aufgaben gut genug
sein.
Diffstat (limited to 'aufgabe4/queue.c')
| -rw-r--r-- | aufgabe4/queue.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/aufgabe4/queue.c b/aufgabe4/queue.c new file mode 100644 index 0000000..62a888c --- /dev/null +++ b/aufgabe4/queue.c @@ -0,0 +1,138 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * © 2010 Michael Stapelberg + * + */ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdbool.h> +#include <string.h> +#include <semaphore.h> +#include <errno.h> + +#include "queue.h" + +static const int queue_size = sizeof(struct queueheader) + (sizeof(struct msg) * 255); + +static int fd; +static uint8_t *shm; +static struct queueheader *shmheader; +static struct msg *shmdata; + +/* + * Sperrt den Semaphor: Nun kann im Shared Memory-Bereich geschrieben werden. + * + */ +static void lock() { + while (1) { + if (sem_wait(&(shmheader->sem)) == -1) { + if (errno == EINTR) + continue; + perror("sem_wait"); + exit(EXIT_FAILURE); + } + break; + } +} + +/* + * Entsperrt den Semaphor. + * + */ +static void unlock() { + sem_post(&(shmheader->sem)); +} + +/* + * Initialisiert das Shared Memory-Segment, bildet es in den Speicher ab und + * initialisiert den Semaphor. + * + */ +void queue_init() { + int flags = O_RDWR | O_CREAT | O_TRUNC; + if ((fd = shm_open("/bts-sem", flags, S_IREAD | S_IWRITE)) == -1) { + perror("shm_open"); + exit(EXIT_FAILURE); + } + + ftruncate(fd, queue_size); + + if ((shm = mmap(0, queue_size, (PROT_READ | PROT_WRITE), + MAP_SHARED, fd, 0)) == MAP_FAILED) { + perror("mmap"); + exit(EXIT_FAILURE); + } + + shmheader = (struct queueheader*)shm; + shmdata = (struct msg*)(shm + sizeof(struct queueheader)); + + shmheader->cur = 0; + shmdata->dir = D_INVALID; + + /* Semaphor initialisieren */ + if (sem_init(&(shmheader->sem), 1, 1) != 0) { + perror("sem_init"); + exit(EXIT_FAILURE); + } +} + +/* + * Hängt den übergebenen Wert in die Queue. + * + */ +struct msg *queue_write(uint8_t dir, uint8_t data) { + struct msg msg; + msg.dir = dir; + msg.data = data; + + uint8_t next; + if (shmheader->cur == 255) + next = 0; + else next = shmheader->cur + 1; + + lock(); + struct msg *curmsg = shmdata + (shmheader->cur * sizeof(struct msg)); + struct msg *nextmsg = shmdata + (next * sizeof(struct msg)); + memcpy(nextmsg, &msg, sizeof(struct msg)); + if (curmsg->dir == D_INVALID) + shmheader->cur = next; + unlock(); + + return nextmsg; +} + +/* + * Gibt die Quelle der derzeit zu verarbeitenden Nachricht zurück. + * + */ +uint8_t queue_get_dir() { + struct msg *curmsg = shmdata + (shmheader->cur * sizeof(struct msg)); + return curmsg->dir; +} + +/* + * Gibt den Wert der derzeit zu verarbeitenden Nachricht zurück und invalidiert + * diese. + * + */ +uint8_t queue_get_data() { + uint8_t data; + + struct msg *curmsg = shmdata + (shmheader->cur * sizeof(struct msg)); + data = curmsg->data; + + lock(); + curmsg->dir = D_INVALID; + if (shmheader->cur == 255) + shmheader->cur = 0; + else shmheader->cur++; + unlock(); + + return data; +} |
