===== März 2006 ===== ==== Aufgabe 1 ==== * a) 2 (http://de.wikipedia.org/wiki/RAID_5#RAID_5:_Leistung_.2B_Parit.C3.A4t) * b) 3 * c) 1 ist als falsch gedacht und unpassend formuliert (hat juk, glaube ich, gesagt; gemeint ist, daß alle Adressen zum Zeitpunkt des Programmstarts aufgelöst werden, aber das ist nicht richtig, weil es Adreßbezüge gibt, die vorher aufgelöst werden können.) * d) 1 * e) 2 * f) 4 * g) 1 * h) 4 * i) 3 * j) 2 * k) 4 * l) 2 * m) 3 * n) 3 ==== Aufgabe 2 ==== Zum testen müssen sem.c und sem.h selbst geschrieben werden. * a) /* author: Noya, Sven Pfaller */ #include #include #include #include #include #include #include #include #include #include #include #include /* "sem.h" pthread_mutex_t // for (int i void *xxx(void *) string.h & unlink */ /* Includes, Funktionsdeklarationen, globale Variablen */ #include #include "sem.h" #include #define NBUFFER 9 #define PORT 7654 #define URL "localhost" int main(int argc, char **argv); static void process_jobs(); static void job(FILE *file); static void *process_queue(void *data); static void thread_error(char *msg); static void error(char *msg); static void num_error(char *msg, int num); static FILE *buffer[NBUFFER]; static int bread; static int bwrite; static int sock; static SEM *semfree; static SEM *semfill; static pthread_mutex_t block; /* Funktion main */ int main(int argc, char **argv) { /* lokale Variablen und was man sonst am Anfang so vorbereitet */ pthread_t thread; struct sockaddr_in addr; struct hostent *host; int e; int i; bread = 0; bwrite = 0; /* Semaphore erzeugen und initialisieren */ semfree = sem_init(NBUFFER); semfill = sem_init(0); /* queue-Threads erzeugen */ for (i = 1; i < argc; i++) { if ((e = pthread_create(&thread, NULL, process_queue, (void *) argv[i])) != 0) { num_error("pthread_create", e); } } /* Verbindung zu Printserver aufbauen */ host = gethostbyname(URL); if (host == NULL) error("gethostbyname"); sock = socket(PF_INET, SOCK_STREAM, 0); if (sock == -1) error("socket"); addr.sin_family = AF_INET; addr.sin_port = htons(PORT); memcpy(&addr.sin_addr.s_addr, host->h_addr_list[0], host->h_length); if (connect(sock, (const struct sockaddr *) &addr, sizeof(struct sockaddr_in)) == -1) error("connect"); /* Auftraege bearbeiten, Ende main */ process_jobs(); /* Ende von main - wird nie erreicht */ return 0; } /* Funktionen process_jobs */ static void process_jobs() { FILE *cfile; FILE *file; char fname[PATH_MAX + 2]; while (1) { P(semfill); cfile = buffer[bread]; bread = (bread + 1) % NBUFFER; V(semfree); if (fgets(fname, PATH_MAX + 2, cfile) == NULL) error("fgets"); fname[strlen(fname) - 1] = '\0'; printf(".global: processing document (%s)...\n", fname); file = fopen(fname, "r"); if (file == NULL) error("fopen"); job(file); printf(".global: processing document (%s) done\n", fname); fclose(cfile); fclose(file); /* if unlinking failes, ignore it */ unlink(fname); } } /* Funktion job */ static void job(FILE *file) { struct stat info; int fd; FILE *sockfp; char buf[1024]; fd = fileno(file); sockfp = fdopen(sock, "w"); if (sockfp == NULL) error("fdopen"); if (fstat(fd, &info) == -1) error("fstat"); if (fprintf(sockfp, "print job length=%i\n", info.st_size) < 0) error("fprintf"); while (fgets(buf, 1024, file) != NULL) { if (fputs(buf, sockfp) == EOF) error("fputs"); } if (feof(file) == 0) error("fgets"); fflush(sockfp); } /* Funktion process_queue */ static void *process_queue(void *data) { char *dirname; DIR *dir; struct dirent *entry; FILE *cfile; char path[PATH_MAX + 1]; dirname = (char *) data; while (1) { dir = opendir(dirname); if (dir == NULL) thread_error("opening directory failed"); errno = 0; while ((entry = readdir(dir)) != NULL) { if (entry->d_name[0] == 'c') { snprintf(path, PATH_MAX + 1, "%s/%s", dirname, entry->d_name); cfile = fopen(path, "r"); if (cfile != NULL) { P(semfree); pthread_mutex_lock(&block); buffer[bwrite] = cfile; bwrite = (bwrite + 1) % NBUFFER; pthread_mutex_unlock(&block); V(semfill); printf("%s: found document control file (%s), added to global queue\n", dirname, entry->d_name); /* if unlinking failes, ignore it */ unlink(path); } } errno = 0; } if (errno != 0) thread_error("reading from directory failed"); closedir(dir); } } static void thread_error(char *msg) { perror(msg); pthread_exit(NULL); } static void error(char *msg) { perror(msg); exit(1); } static void num_error(char *msg, int num) { printf("%s: %s\n", msg, strerror(num)); exit(1); } * b) # author: Noya, Sven Pfaller (kalterregen@gmx.net) CFLAGS=-ansi -pedantic -D_POSIX_SOURCE -g .PHONY: clean lpqmanager: sem.o lpqmanager.o gcc ${CFLAGS} -o lpqmanager lpqmanager.o sem.o -lpthread sem.o: sem.c sem.h gcc ${CFLAGS} -c -o sem.o sem.c lpqmanager.o: lpqmanager.c gcc ${CFLAGS} -c -o lpqmanager.o lpqmanager.c clean: rm -f *.o rm -f lpqmanager ==== Aufgabe 3 ==== ==== Aufgabe 4 ==== * a) * b) * c) * d)