Du befindest dich hier: FSI Informatik » jahrgaenge » 2006 » "Muster"-Lösungen » "Muster"-Lösungen zu Klausuren aus Softwaresysteme 1 » Vordiplomsklausuren » März 2005   (Übersicht)

März 2005

Aufgabe 1

  • a) 3 (?)
  • b) 1
  • c) 3 (Quelle)
  • d) 3
  • e) 1
  • f) 1(?) das ist mal ne wirklich interessante frage…

→ Wenn zu einem Zeitpunkt nur ein Prozeß reell laufen kann, weil nur ein Prozessor da ist, und wenn dabei keine Verdrängung stattfinden kann, kommt keine Nebenläufigkeit zustande. Also müssen die Zugriffe nicht koordiniert werden.

  • g) 3
  • h) 2
  • i) 4
  • j) 4 (?) ich tippe auf 2: eine seite = 4096, hauptspeicher = 4GB ⇒ ca. 2000 seiten im system, jeder eintrag in der tabelle 4 byte (32bit) macht dann 2000 x 4 = 8000 byte… → 4 ist korrekt, Rechnung: 4294967296 / 4096 *32 / 8 = 4194304 Ich will nen TR!
  • k) 3
  • l) 2
  • m) 4
  • n) 2
  • o) 4

Aufgabe 2

  • a)
/* includes */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/stat.h>
 
/* Funktionsdeklarationen, globale Variablen */
 
#define MAX_LEN 128
 
int main(int argc, char **argv);
static void serve(int sock);
static void prattr(char *filename);
static void error(char *msg);
static void sighandler(int sig);
 
/* Funktion main */
 
int main(int argc, char **argv)
{
	/* lokale Variablen und was man sonst am Anfang so vorbereitet */
 
	int port;
	int sock;
	struct sockaddr_in addr;
	struct sockaddr_in client_addr;
	int client_addr_len = sizeof(struct sockaddr_in);
	int client_sock;
	int pid;
	struct sigaction action;
 
	if (argc != 2) {
		printf("usage: fileattrd PORT\n");
		exit(1);
	}
	port = atoi(argv[1]);
 
	/* Ein Signal-Handler für SIGCHLD (ein Kindprozess stirbt) wird installiert. So können Zombies mit waitpid abgeholt werden. */
	action.sa_handler = sighandler;
	sigemtpyset(&action.sa_mask);
	action.flags = SA_RESTART;
	sigaction(SIGCHLD, &action, NULL);
 
	/* Socket oeffnen */
 
	sock = socket(PF_INET, SOCK_STREAM, 0);
	if (sock == -1) error("creating socket failed");
 
	/* Socket an angegebenen Port und beliebige IP-Adressen binden */
 
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(sock, (const struct sockaddr *) &addr, sizeof(struct sockaddr_in)) == -1) error("binding socket failed");
 
	/* Warteschlange ankommender Verbindungen auf 5 einstellen */
 
	if (listen(sock, 5) == -1) error("listening failed");
 
	/* Server-Schleife */
 
	while (1) {
 
		/* Verbindung aufnehmen */
 
		client_sock = accept(sock, (struct sockaddr *) &client_addr, &client_addr_len);
		if (client_sock == -1) error("accepting failed");
 
		/* Prozess zur Kommandoausführung erzeugen */
 
		pid = fork();
		switch(pid) {
 
		/* Fehler bei Prozesserzeugung */
 
		case -1:
			error("forking failed");
			break;
 
		/* Sohnprozess */
 
		case 0:
			serve(client_sock);
			break;
 
		/* Vaterprozess */
 
		default:
			break;
		}
	}
 
} /* Ende Funktion main */
 
/* serve-Funktion */
 
static void serve(int sock) {
	FILE *f;
	char buffer[MAX_LEN + 2];
 
	f = fdopen(sock, "rw");
	if (f == NULL) error("opening socket for reading failed");
 
	errno = 0;
	while (fgets(buffer, MAX_LEN + 1, f) != NULL) {
		buffer[strlen(buffer) - 1] = '\0';
		prattr(buffer);
		errno = 0;
	}
	if (errno != 0) error("reading string failed");
 
	fclose(f);
	close(sock);
 
	exit(0);
}
 
/* prattr-Funktion */
 
static void prattr(char *filename) {
	struct stat info;
 
	if (stat(filename, &info) == -1) {
		printf("%s %s\n", filename, strerror(errno));
		return;
	}
 
	if (S_ISREG(info.st_mode)) {
		printf("%s F %i\n", filename, info.st_size);
	} else if (S_ISDIR(info.st_mode)) {
		printf("%s D\n", filename);
	} else {
		printf("%s X\n", filename);
	}
}
 
/* weitere Funktionen, falls benoetigt */
 
static void error(char *msg) {
	perror(msg);
	exit(1);
}
 
static void sighandler(int sig) {
	int pid;
	int status;
 
	while ((pid = waitpid(-1, &status, WNOHANG)) != 0) {
		if (pid == -1) error("waiting for zombies failed");
	}
}

Alternative Lösung: Diese schreibt die angeforderte Information auch wieder auf den socket zurück

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
 
/* fehlende includes */
#include <sys/stat.h>
#include <string.h>
 
#define DEFAULT_PORT 31337
 
static void serve(int socket);
static void prattr(char *filename);
static void sigchld_handler_install(void);
static void sigchld_handler(int sig);
 
int main(int argc, char *argv[]) {
    int sock;
    unsigned short port;
    struct sockaddr_in saddr;
 
    if (argc > 1) {
        port = atoi(argv[1]);
    } else {
        port = DEFAULT_PORT;
    }
 
    sigchld_handler_install();
 
    sock = socket(PF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket");
        return EXIT_FAILURE;
    }
 
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    saddr.sin_port = htons(port);
 
    if (bind(sock, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) {
        perror("bind");
        return EXIT_FAILURE;
    }
 
    if (listen(sock, 5) == -1) {
        perror("listen");
        return EXIT_FAILURE;
    }
 
    printf("Listening on port %d\n", port);
 
    while (1) {
        pid_t pid;
        int clsock;
        struct sockaddr clsaddr;
        socklen_t clsaddr_len = sizeof(clsaddr);
 
        clsock = accept(sock, &clsaddr, &clsaddr_len);
        if (clsock == -1) {
            perror("accept");
            continue;
        }
 
        switch(pid = fork()) {
            case -1:
                /* error */
                perror("fork");
                return EXIT_FAILURE;
 
                break;
            case 0:
                /* child */
                close(sock);
 
                serve(clsock);
 
                close(clsock);
                exit(EXIT_SUCCESS);
 
                break;
            case 1:
                /* parent */
                close(clsock);
 
                break;
        }
    }
 
    return EXIT_SUCCESS;
}
 
static void serve(int socket) {
    char file[128+2];
    FILE *fd = fdopen(socket, "r+");
 
    if (dup2(socket, fileno(stdout)) == -1) {
        perror("dup2");
        exit(EXIT_FAILURE);
    }
 
    while(fgets(file, 128+2, fd) != NULL) {
        file[strlen(file)-1] = '\0';
 
        prattr(file);
    }
}
 
static void prattr(char *filename) {
    struct stat statbuf;
 
    if (stat(filename, &statbuf) == -1) {
        printf("%s %s\n", filename, strerror(errno));
    } else {
        if (S_ISDIR(statbuf.st_mode)) {
            printf("%s D\n", filename);
        } else if (S_ISREG(statbuf.st_mode)) {
            printf("%s F %ld\n", filename, (unsigned long) statbuf.st_size);
        } else {
            printf("%s X\n", filename);
        }
    }
    fclose(fd);
}
 
static void sigchld_handler_install(void) {
    struct sigaction sa;
 
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = sigchld_handler;
    sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }
}
 
static void sigchld_handler(int sig) {
    int errsvr;
    int status;
    pid_t pid;
 
    errsvr = errno;
 
    while((pid = waitpid(-1, &status, WNOHANG)) != 0) {
        if (pid == -1) {
            if (errno == ECHILD) {
                break;
            }
            perror("waitpid");
            break;
        }
    }
 
    errno = errsvr;
}
  • b)
fileattrd: fileattrd.o

.PHONY: clean
clean:
	$(RM) fileattrd fileattrd.o

#restliche regeln sind alle implizit vorhanden

Aufgabe 3

  • a)
  • b)
  • c)
  • d)

Aufgabe 4