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 | |
| 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')
| -rw-r--r-- | aufgabe4/Makefile | 3 | ||||
| -rw-r--r-- | aufgabe4/conv.c | 30 | ||||
| -rw-r--r-- | aufgabe4/log.c | 30 | ||||
| -rw-r--r-- | aufgabe4/main.c | 7 | ||||
| -rw-r--r-- | aufgabe4/monitor.c | 21 | ||||
| -rw-r--r-- | aufgabe4/queue.c | 138 | ||||
| -rw-r--r-- | aufgabe4/queue.h | 25 | ||||
| -rw-r--r-- | aufgabe4/statistic.c | 38 |
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); } |
