aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aufgabe4/Makefile3
-rw-r--r--aufgabe4/conv.c30
-rw-r--r--aufgabe4/log.c30
-rw-r--r--aufgabe4/main.c7
-rw-r--r--aufgabe4/monitor.c21
-rw-r--r--aufgabe4/queue.c138
-rw-r--r--aufgabe4/queue.h25
-rw-r--r--aufgabe4/statistic.c38
8 files changed, 283 insertions, 9 deletions
diff --git a/aufgabe4/Makefile b/aufgabe4/Makefile
index d08af51..2d8d2a8 100644
--- a/aufgabe4/Makefile
+++ b/aufgabe4/Makefile
@@ -4,7 +4,8 @@ all:
gcc -Wall -c -o statistic.o statistic.c
gcc -Wall -c -o monitor.o monitor.c
gcc -Wall -c -o main.o main.c
- gcc -o pk main.o conv.o log.o statistic.o monitor.o
+ gcc -Wall -c -o queue.o queue.c
+ gcc -o pk main.o conv.o log.o statistic.o monitor.o queue.o -lrt
clean:
rm -f *.o
diff --git a/aufgabe4/conv.c b/aufgabe4/conv.c
index efa8200..919965c 100644
--- a/aufgabe4/conv.c
+++ b/aufgabe4/conv.c
@@ -1,18 +1,44 @@
/*
* vim:ts=4:sw=4:expandtab
+ *
+ * © 2010 Michael Stapelberg
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include "queue.h"
+
+/*
+ * Conv-Prozess. Generiert Zufallszahlen und schickt sie an den Log-Prozess
+ * sowie an den Statistik-Prozess.
+ *
+ */
void conv() {
- printf("conv started\n");
+ int number;
+ struct msg *first;
+ struct msg *second;
for (;;) {
+ /* Zufallszahl generieren */
+ number = rand();
+
+ /* Zahl zweimal in die Queue schreiben: Einmal zum loggen, einmal für
+ * den Statistik-Prozess */
+ first = queue_write(D_CONV_TO_LOG, number);
+ second = queue_write(D_CONV_TO_STAT, number);
+
+ /* Warten, bis die Zufallszahl aus der Queue geholt wurde */
+ while (first->dir == D_CONV_TO_LOG ||
+ second->dir == D_CONV_TO_STAT)
+ usleep(1);
}
}
+/*
+ * Cleanup-Funktion. Beendet den Prozess.
+ *
+ */
void conv_cleanup() {
- printf("conv cleanup\n");
_exit(EXIT_SUCCESS);
}
diff --git a/aufgabe4/log.c b/aufgabe4/log.c
index 405cdbd..105f2d3 100644
--- a/aufgabe4/log.c
+++ b/aufgabe4/log.c
@@ -1,18 +1,44 @@
/*
* vim:ts=4:sw=4:expandtab
+ *
+ * © 2010 Michael Stapelberg
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include "queue.h"
+
+FILE *file;
+
+/*
+ * Logprozess. Schreibt die empfangenen Daten in eine Datei.
+ *
+ */
void log() {
- printf("log started\n");
- for (;;) {
+ /* Datei zum Schreiben öffnen */
+ if ((file = fopen("log.txt", "w")) == NULL) {
+ perror("fopen");
+ exit(EXIT_FAILURE);
+ }
+
+ while (1) {
+ /* Wir warten auf Nachrichten des CONV-Prozesses */
+ while (queue_get_dir() != D_CONV_TO_LOG)
+ usleep(1);
+
+ uint8_t data = queue_get_data();
+ fprintf(file, "%d\n", data);
}
}
+/*
+ * Cleanup-Funktion (wird als Signalhandler gesetzt). Schließt die Logdatei.
+ *
+ */
void log_cleanup() {
printf("log cleanup\n");
+ fclose(file);
_exit(EXIT_SUCCESS);
}
diff --git a/aufgabe4/main.c b/aufgabe4/main.c
index f876f54..c990f3d 100644
--- a/aufgabe4/main.c
+++ b/aufgabe4/main.c
@@ -1,5 +1,7 @@
/*
* vim:ts=4:sw=4:expandtab
+ *
+ * © 2010 Michael Stapelberg
*
*/
#include <stdio.h>
@@ -13,6 +15,7 @@
#include "log.h"
#include "monitor.h"
#include "statistic.h"
+#include "queue.h"
typedef void (*funcptr)();
@@ -69,6 +72,10 @@ pid_t fork_child(funcptr work, funcptr cleanup) {
*
*/
int main() {
+
+ /* Shared Memory-Bereich initialisieren */
+ queue_init();
+
pconv = fork_child(conv, conv_cleanup);
plog = fork_child(log, log_cleanup);
pstatistic = fork_child(statistic, statistic_cleanup);
diff --git a/aufgabe4/monitor.c b/aufgabe4/monitor.c
index b631e59..e2bf015 100644
--- a/aufgabe4/monitor.c
+++ b/aufgabe4/monitor.c
@@ -1,18 +1,35 @@
/*
* vim:ts=4:sw=4:expandtab
+ *
+ * © 2010 Michael Stapelberg
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include "queue.h"
+
+/*
+ * Monitor-Prozess. Gibt die empfangenen Daten aus.
+ *
+ */
void monitor() {
- printf("monitor started\n");
for (;;) {
+ /* Wir warten auf Nachrichten des CONV-Prozesses */
+ while (queue_get_dir() != D_STAT_TO_MON)
+ usleep(1);
+
+ uint8_t data = queue_get_data();
+ printf("Empfangenes Datum: %d\n", data);
+ fflush(stdout);
}
}
+/*
+ * Cleanup-Funktion. Beendet den Prozess.
+ *
+ */
void monitor_cleanup() {
- printf("monitor cleanup\n");
_exit(EXIT_SUCCESS);
}
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;
+}
diff --git a/aufgabe4/queue.h b/aufgabe4/queue.h
new file mode 100644
index 0000000..3c8a1e3
--- /dev/null
+++ b/aufgabe4/queue.h
@@ -0,0 +1,25 @@
+#ifndef _QUEUE_H
+#define _QUEUE_H
+#include <stdbool.h>
+#include <stdint.h>
+#include <semaphore.h>
+
+struct queueheader {
+ uint8_t msgs;
+ uint8_t cur;
+ sem_t sem;
+} __attribute__((packed));
+
+struct msg {
+ uint8_t dir;
+ uint8_t data;
+} __attribute__((packed));
+
+enum { D_CONV_TO_LOG = 0, D_CONV_TO_STAT, D_STAT_TO_MON, D_INVALID };
+
+void queue_init();
+struct msg *queue_write(uint8_t dir, uint8_t data);
+uint8_t queue_get_data();
+uint8_t queue_get_dir();
+
+#endif
diff --git a/aufgabe4/statistic.c b/aufgabe4/statistic.c
index b83776a..cf59217 100644
--- a/aufgabe4/statistic.c
+++ b/aufgabe4/statistic.c
@@ -1,18 +1,52 @@
/*
* vim:ts=4:sw=4:expandtab
+ *
+ * © 2010 Michael Stapelberg
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include "queue.h"
+
+static uint8_t saved[5];
+static uint8_t cnt;
+
+/*
+ * Statistik-Prozess. Empfängt je 5 Werte, bildet das arithmetische Mittel und
+ * schickt dieses an den Monitor-Prozess.
+ *
+ */
void statistic() {
- printf("statistic started\n");
+ uint8_t c, avg;
+
+ cnt = 0;
for (;;) {
+ /* Wir warten auf Nachrichten des CONV-Prozesses */
+ while (queue_get_dir() != D_CONV_TO_STAT)
+ usleep(1);
+
+ uint8_t data = queue_get_data();
+ saved[cnt] = data;
+ if (cnt == 4) {
+ /* Wir haben 5 Werte gespeichert, können nun also den Mittelwert
+ * bilden. */
+ avg = 0;
+ for (c = 0; c < 5; c++)
+ avg += saved[c];
+ avg /= 5;
+ queue_write(D_STAT_TO_MON, avg);
+ cnt = 0;
+ } else cnt++;
+
}
}
+/*
+ * Cleanup-Funktion. Beendet den Prozess.
+ *
+ */
void statistic_cleanup() {
- printf("statistic cleanup\n");
_exit(EXIT_SUCCESS);
}