aboutsummaryrefslogtreecommitdiff
path: root/aufgabe4/queue.c
diff options
context:
space:
mode:
authorMichael Stapelberg <michael@stapelberg.de>2010-12-06 19:55:19 +0100
committerMichael Stapelberg <michael@stapelberg.de>2010-12-06 19:55:19 +0100
commit0c9d712a77bbede4808142944776d35f502bffa7 (patch)
tree1955e375d404308aa1d79b9d355e37dba739b9bf /aufgabe4/queue.c
parent9af2bea582c083653c08abb965eba6f63de997fa (diff)
downloadprozesskommunikation-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.c138
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;
+}