aboutsummaryrefslogtreecommitdiff
path: root/aufgabe3/main.c
blob: 89506138d04d3cdc0a15e7a019121672bb802f3c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
 * vim:ts=4:sw=4:expandtab
 *
 */
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "conv.h"
#include "log.h"
#include "monitor.h"
#include "statistic.h"
#include "queue.h"

typedef void (*funcptr)();

pid_t pconv;
pid_t plog;
pid_t pstatistic;
pid_t pmonitor;

/*
 * Signalhandler für SIGTERM. Sendet SIGINT an die 4 Prozesse.
 *
 */
void sigterm() {
    kill(pconv, SIGINT);
    kill(plog, SIGINT);
    kill(pstatistic, SIGINT);
    kill(pmonitor, SIGINT);
}

/*
 * fork()t einen neuen Prozess. In diesem Prozess wird die übergebene Funktion
 * work() aufgerufen, außerdem wird der Signalhandler cleanup() installiert für
 * das Signal SIGINT.
 *
 */
pid_t fork_child(funcptr work, funcptr cleanup) {
    pid_t pid = fork();
    if (pid == 0) {
        /* child process */
        signal(SIGINT, cleanup);

        work();

        /* Die Prozesse laufen endlos. Daher beenden wir mit Fehlercode, sofern
         * die Prozessfunktion doch zurückkehrt. */
        exit(EXIT_FAILURE);
    }

    if (pid == -1) {
        /* error */
        perror("fork()");
        exit(EXIT_FAILURE);
    }

    /* parent process */
    printf("forked\n");
    return pid;
}

mqd_t mqueue_init(const char *queue_name) {
    mqd_t msgqueue_id;

    /* Eventuell existierende unbenutzte Message Queue terminieren,
     * um Fehlern durch - eventuell bestehende - Datenreste vorzubeugen.
     */
    mq_unlink(queue_name);

    /*
     * Festlegung der Attribute.
     */
    struct mq_attr *attributes = calloc(1, sizeof(struct mq_attr));
    if (attributes != NULL) { /* NULL als Attribut nimmt die Standard Werte */
        attributes->mq_flags = 0; /* Queue blockiert bei mq_send()/mq_receive() */
        attributes->mq_maxmsg = 20; /* maximal 20 Messages in der Queue */
        attributes->mq_msgsize = 9; /* Maximale Länge einer Nachricht */
        attributes->mq_curmsgs = 0; /* Anzahl der Messages momentan in der Queue */
    }

    /*
     * Erstellung der Message Queue.
     */
    msgqueue_id = mq_open(queue_name, O_RDWR | O_CREAT, S_IRWXU | S_IRWXG, attributes);
    if (msgqueue_id == -1){
        perror("mq_init");
        exit(EXIT_FAILURE);
    }

    return msgqueue_id;
}

/*
 * main-Funktion. Startet die 4 Prozesse, registriert einen signal-handler für
 * SIGTERM (dieser sendet SIGINT an die 4 Prozesse) und wartet schließlich auf
 * das Ende der Prozesse.
 */
int main() {

    /*
     * Erstellung der Queues.
     */
    mqueue_init(MQ_TO_LOG);
    mqueue_init(MQ_TO_STATISTIC);
    mqueue_init(MQ_TO_MONITOR);

    pconv = fork_child(conv, conv_cleanup);
    plog = fork_child(logmsg, logmsg_cleanup);
    pstatistic = fork_child(statistic, statistic_cleanup);
    pmonitor = fork_child(monitor, monitor_cleanup);

    signal(SIGTERM, sigterm);

    int status;
    waitpid(pconv, &status, 0);
    waitpid(plog, &status, 0);
    waitpid(pstatistic, &status, 0);
    waitpid(pmonitor, &status, 0);

    return EXIT_SUCCESS;
}