Snake85
29-10-2008, 21:21
Hi,
ich simuliere grad das Leser-Schreiber-Problem und möchte es mit Threads und Semaphoren bewältigen.
Allerdings bekomm ich immer ein Segmentation Fault (core dumped), wenn ich auch die exit-Status-Variable zugreifen will, die ich bei pthread_join(...) angegeben habe:
In dem Bereich unter
/* auf alle Thread-Ende warten und Exit-Status ausgeben */
genau bei printf("Exit-Status Thread %i: %i\n", tid[i], *status[i]);
Vermutlich muss ich Speicher anfordern im Zusammenhang mit *status[i], aber ich komm einfach nicht auf die Lösung wie, wo und wieviel.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <synch.h>
#include <unistd.h>
#include "error.h"
/* zu Debug-Szecken */
#define DEBUG 1
/* Groesse der Datenbank */
#define DB_SIZE 5
#define WRITER_INCREASE 10
#define MAX_SLEEP_TIME 5
#define LOOPS 4
/* globale Datenbank (Zahlenfeld) */
int database[DB_SIZE];
/* Schutz der Datenbank */
sema_t db;
/* Schutz der Variablen rc */
pthread_mutex_t mutex;
/* Zahl der Leser in Datenbank */
int grc;
/* Funktionsprototypen */
int initDB();
void destroyDB();
void *reader(void *arg);
void *writer(void *arg);
int main(int argc, char* argv[]) {
pthread_t *tid;
int rc, i, cntReader, cntWriter, cntTid;
int **status;
/* Argumentenanzahl ueberpruefen */
if(argc != 3) {
error_exit("usage: ./rwcoop #reader #writer", 10);
}
/* Datenbank initialisieren */
initDB();
/* Argumente verarbeiten */
cntReader = atoi(argv[1]);
if(cntReader < 0) {
error_exit("error: incorrect number of readers", 20);
}
cntWriter = atoi(argv[2]);
if(cntWriter < 0) {
error_exit("error: incorrect number of writers", 21);
}
/* reader starten */
for(i=0; i<cntReader; i++) {
/* Thread erzeugen, reader aufrufen */
tid[cntTid] = (pthread_t)malloc(sizeof(pthread_t));
rc = pthread_create(&(tid[cntTid]), NULL, reader, &(tid[cntTid]));
cntTid++;
if(rc != 0) {
error_exit("error creating reader thread", 30);
}
}
/* writer starten */
for(i=0; i<cntWriter; i++) {
/* Thread erzeugen, writer aufrufen */
tid[cntTid] = (pthread_t)malloc(sizeof(pthread_t));
rc = pthread_create(&(tid[cntTid]), NULL, writer, &(tid[cntTid]));
cntTid++;
if(rc != 0) {
error_exit("error creating writer thread", 50);
}
}
/* jedem Thread seinen Platz fuer Exit-Status zusichern */
status = malloc(cntTid*sizeof(int));
/* auf alle Thread-Ende warten und Exit-Status ausgeben */
for(i=0; i<cntTid; i++) {
/* auf Threadende warten */
if(DEBUG) printf("1\n");
status[i] = malloc(sizeof(int));
if(DEBUG) printf("1,5\n");
rc = pthread_join(tid[i], (void **)&status[i]);
if(DEBUG) printf("2\n");
if(rc != 0) {
error_exit("error joining threads", i);
}
/* Exit-Status des Threads ausgeben */
if(DEBUG) printf("2,5\n");
printf("Exit-Status Thread %i: %i\n", tid[i], *status[i]);
/* angeforderten Speicher wieder freigeben */
if(DEBUG) printf("3\n");
free(&tid[i]);
if(DEBUG) printf("3,5\n");
/* free(status[i]);*/
if(DEBUG) printf("4\n");
}
/* Datenbank aufloesen: Mutex, Semaphore freigeben */
if(DEBUG) printf("5\n");
destroyDB();
/* free(status);*/
if(DEBUG) printf("6\n");
/* THE END */
return 1;
}
int initDB() {
int rc, i;
/*Mutex initialisieren */
rc = pthread_mutex_init(&mutex, NULL);
if(rc != 0) {
error_exit("error initialising mutex", 60);
}
/* Semaphore initialisieren */
rc = sema_init(&db, 1, USYNC_THREAD, NULL);
if(rc != 0) {
error_exit("error initialising semaphore",62);
}
/* Datenbank initialisieren*/
for(i=0; i<DB_SIZE; i++) {
database[i] = i;
}
/* Datenbankgroesse zurueckgeben */
return sizeof(database)/sizeof(int);
}
void destroyDB() {
int rc;
/* Mutex freigeben */
rc = pthread_mutex_destroy(&mutex);
if(rc != 0) {
error_msg("error destroying mutex", 65);
}
/* Semaphore freigeben */
rc = sema_destroy(&db);
if(rc != 0) {
error_msg("error destroying semaphore", 66);
}
}
void *reader(void *arg) {
int rc, i, nr;
unsigned int pause;
/* Argument auswerten */
if(DEBUG) printf("7\n");
nr = *(int *)arg;
if(DEBUG) printf("8\n");
/* Datenbank ausgeben */
for(i=0; i<DB_SIZE; i++) {
if(DEBUG) printf("9\n");
/* wait(mutex), Zugriff auf Zaehler sperren */
pthread_mutex_lock(&mutex);
if(DEBUG) printf("10\n");
/* Zahl der Leser hochzaehlen */
grc++;
if(DEBUG) printf("11\n");
if(grc == 1) {
/* wait(db), Schreiber aussperren, falls dies der erste Leser */
if(DEBUG) printf("12\n");
sema_wait(&db);
if(DEBUG) printf("13\n");
}
/* signal(mutex), Zugriff auf Zaehler freigeben */
pthread_mutex_unlock(&mutex);
if(DEBUG) printf("14\n");
/* lesenden Datenbankzugriff ausfuehren */
printf("Thread %i reads position %i: %i\n", nr, i, database[i]);
/* wait(mutex), Zugriff auf Zaehler sperren */
if(DEBUG) printf("15\n");
pthread_mutex_lock(&mutex);
if(DEBUG) printf("16\n");
/* Zahl der Leser runterzaehlen */
grc--;
if(grc == 0) {
/* signal(db), Schreiber zulassen, falls dies der letzte Leser */
if(DEBUG) printf("17\n");
sema_post(&db);
if(DEBUG) printf("18\n");
}
/* signal(mutex), Zugriff auf Zaehler freigeben */
if(DEBUG) printf("19\n");
pthread_mutex_unlock(&mutex);
if(DEBUG) printf("20\n");
/* kleine Pause einlegen */
if(DEBUG) printf("21\n");
pause = (unsigned int)(rand()%MAX_SLEEP_TIME);
printf("Thread %i sleeps %i seconds\n", nr, pause);
rc = sleep(pause);
if(rc > 0) {
error_msg("error, i'm still a tired reader", 70);
}
if(DEBUG) printf("22\n");
}
/* Thread beenden */
rc = 42;
if(DEBUG) printf("23\n");
pthread_exit((void *)&rc);
}
void *writer(void *arg) {
int rc, i, nr;
unsigned int pause;
/* Argument auswerten */
if(DEBUG) printf("24\n");
nr = *(int *)arg;
if(DEBUG) printf("25\n");
/* Datenbank manipulieren */
for(i=0; i<DB_SIZE; i++) {
if(DEBUG) printf("26\n");
/* wait(db) */
sema_wait(&db);
if(DEBUG) printf("27\n");
/* schreibenden Datenbankzugriff ausfuehren */
if(DEBUG) printf("28\n");
database[i] += WRITER_INCREASE;
if(DEBUG) printf("29\n");
printf("Thread %i writes to position %i: %i\n", nr, i, database[i]);
/* signal(db) */
if(DEBUG) printf("30\n");
sema_post(&db);
if(DEBUG) printf("31\n");
/* kleine Pause einlegen */
pause = (unsigned int)(rand()%MAX_SLEEP_TIME);
printf("Thread %i sleeps %i seconds\n", nr, pause);
rc = sleep(pause);
if(rc > 0) {
error_msg("error, i'm still a tired writer", 90);
}
if(DEBUG) printf("32\n");
}
/* Thread beenden */
rc = 4711;
if(DEBUG) printf("33\n");
pthread_exit((void *)&rc);
}
Sorry, für den Haufen printf's, aber so sieht man wo der Fehler begraben liegt ;)
ich simuliere grad das Leser-Schreiber-Problem und möchte es mit Threads und Semaphoren bewältigen.
Allerdings bekomm ich immer ein Segmentation Fault (core dumped), wenn ich auch die exit-Status-Variable zugreifen will, die ich bei pthread_join(...) angegeben habe:
In dem Bereich unter
/* auf alle Thread-Ende warten und Exit-Status ausgeben */
genau bei printf("Exit-Status Thread %i: %i\n", tid[i], *status[i]);
Vermutlich muss ich Speicher anfordern im Zusammenhang mit *status[i], aber ich komm einfach nicht auf die Lösung wie, wo und wieviel.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <synch.h>
#include <unistd.h>
#include "error.h"
/* zu Debug-Szecken */
#define DEBUG 1
/* Groesse der Datenbank */
#define DB_SIZE 5
#define WRITER_INCREASE 10
#define MAX_SLEEP_TIME 5
#define LOOPS 4
/* globale Datenbank (Zahlenfeld) */
int database[DB_SIZE];
/* Schutz der Datenbank */
sema_t db;
/* Schutz der Variablen rc */
pthread_mutex_t mutex;
/* Zahl der Leser in Datenbank */
int grc;
/* Funktionsprototypen */
int initDB();
void destroyDB();
void *reader(void *arg);
void *writer(void *arg);
int main(int argc, char* argv[]) {
pthread_t *tid;
int rc, i, cntReader, cntWriter, cntTid;
int **status;
/* Argumentenanzahl ueberpruefen */
if(argc != 3) {
error_exit("usage: ./rwcoop #reader #writer", 10);
}
/* Datenbank initialisieren */
initDB();
/* Argumente verarbeiten */
cntReader = atoi(argv[1]);
if(cntReader < 0) {
error_exit("error: incorrect number of readers", 20);
}
cntWriter = atoi(argv[2]);
if(cntWriter < 0) {
error_exit("error: incorrect number of writers", 21);
}
/* reader starten */
for(i=0; i<cntReader; i++) {
/* Thread erzeugen, reader aufrufen */
tid[cntTid] = (pthread_t)malloc(sizeof(pthread_t));
rc = pthread_create(&(tid[cntTid]), NULL, reader, &(tid[cntTid]));
cntTid++;
if(rc != 0) {
error_exit("error creating reader thread", 30);
}
}
/* writer starten */
for(i=0; i<cntWriter; i++) {
/* Thread erzeugen, writer aufrufen */
tid[cntTid] = (pthread_t)malloc(sizeof(pthread_t));
rc = pthread_create(&(tid[cntTid]), NULL, writer, &(tid[cntTid]));
cntTid++;
if(rc != 0) {
error_exit("error creating writer thread", 50);
}
}
/* jedem Thread seinen Platz fuer Exit-Status zusichern */
status = malloc(cntTid*sizeof(int));
/* auf alle Thread-Ende warten und Exit-Status ausgeben */
for(i=0; i<cntTid; i++) {
/* auf Threadende warten */
if(DEBUG) printf("1\n");
status[i] = malloc(sizeof(int));
if(DEBUG) printf("1,5\n");
rc = pthread_join(tid[i], (void **)&status[i]);
if(DEBUG) printf("2\n");
if(rc != 0) {
error_exit("error joining threads", i);
}
/* Exit-Status des Threads ausgeben */
if(DEBUG) printf("2,5\n");
printf("Exit-Status Thread %i: %i\n", tid[i], *status[i]);
/* angeforderten Speicher wieder freigeben */
if(DEBUG) printf("3\n");
free(&tid[i]);
if(DEBUG) printf("3,5\n");
/* free(status[i]);*/
if(DEBUG) printf("4\n");
}
/* Datenbank aufloesen: Mutex, Semaphore freigeben */
if(DEBUG) printf("5\n");
destroyDB();
/* free(status);*/
if(DEBUG) printf("6\n");
/* THE END */
return 1;
}
int initDB() {
int rc, i;
/*Mutex initialisieren */
rc = pthread_mutex_init(&mutex, NULL);
if(rc != 0) {
error_exit("error initialising mutex", 60);
}
/* Semaphore initialisieren */
rc = sema_init(&db, 1, USYNC_THREAD, NULL);
if(rc != 0) {
error_exit("error initialising semaphore",62);
}
/* Datenbank initialisieren*/
for(i=0; i<DB_SIZE; i++) {
database[i] = i;
}
/* Datenbankgroesse zurueckgeben */
return sizeof(database)/sizeof(int);
}
void destroyDB() {
int rc;
/* Mutex freigeben */
rc = pthread_mutex_destroy(&mutex);
if(rc != 0) {
error_msg("error destroying mutex", 65);
}
/* Semaphore freigeben */
rc = sema_destroy(&db);
if(rc != 0) {
error_msg("error destroying semaphore", 66);
}
}
void *reader(void *arg) {
int rc, i, nr;
unsigned int pause;
/* Argument auswerten */
if(DEBUG) printf("7\n");
nr = *(int *)arg;
if(DEBUG) printf("8\n");
/* Datenbank ausgeben */
for(i=0; i<DB_SIZE; i++) {
if(DEBUG) printf("9\n");
/* wait(mutex), Zugriff auf Zaehler sperren */
pthread_mutex_lock(&mutex);
if(DEBUG) printf("10\n");
/* Zahl der Leser hochzaehlen */
grc++;
if(DEBUG) printf("11\n");
if(grc == 1) {
/* wait(db), Schreiber aussperren, falls dies der erste Leser */
if(DEBUG) printf("12\n");
sema_wait(&db);
if(DEBUG) printf("13\n");
}
/* signal(mutex), Zugriff auf Zaehler freigeben */
pthread_mutex_unlock(&mutex);
if(DEBUG) printf("14\n");
/* lesenden Datenbankzugriff ausfuehren */
printf("Thread %i reads position %i: %i\n", nr, i, database[i]);
/* wait(mutex), Zugriff auf Zaehler sperren */
if(DEBUG) printf("15\n");
pthread_mutex_lock(&mutex);
if(DEBUG) printf("16\n");
/* Zahl der Leser runterzaehlen */
grc--;
if(grc == 0) {
/* signal(db), Schreiber zulassen, falls dies der letzte Leser */
if(DEBUG) printf("17\n");
sema_post(&db);
if(DEBUG) printf("18\n");
}
/* signal(mutex), Zugriff auf Zaehler freigeben */
if(DEBUG) printf("19\n");
pthread_mutex_unlock(&mutex);
if(DEBUG) printf("20\n");
/* kleine Pause einlegen */
if(DEBUG) printf("21\n");
pause = (unsigned int)(rand()%MAX_SLEEP_TIME);
printf("Thread %i sleeps %i seconds\n", nr, pause);
rc = sleep(pause);
if(rc > 0) {
error_msg("error, i'm still a tired reader", 70);
}
if(DEBUG) printf("22\n");
}
/* Thread beenden */
rc = 42;
if(DEBUG) printf("23\n");
pthread_exit((void *)&rc);
}
void *writer(void *arg) {
int rc, i, nr;
unsigned int pause;
/* Argument auswerten */
if(DEBUG) printf("24\n");
nr = *(int *)arg;
if(DEBUG) printf("25\n");
/* Datenbank manipulieren */
for(i=0; i<DB_SIZE; i++) {
if(DEBUG) printf("26\n");
/* wait(db) */
sema_wait(&db);
if(DEBUG) printf("27\n");
/* schreibenden Datenbankzugriff ausfuehren */
if(DEBUG) printf("28\n");
database[i] += WRITER_INCREASE;
if(DEBUG) printf("29\n");
printf("Thread %i writes to position %i: %i\n", nr, i, database[i]);
/* signal(db) */
if(DEBUG) printf("30\n");
sema_post(&db);
if(DEBUG) printf("31\n");
/* kleine Pause einlegen */
pause = (unsigned int)(rand()%MAX_SLEEP_TIME);
printf("Thread %i sleeps %i seconds\n", nr, pause);
rc = sleep(pause);
if(rc > 0) {
error_msg("error, i'm still a tired writer", 90);
}
if(DEBUG) printf("32\n");
}
/* Thread beenden */
rc = 4711;
if(DEBUG) printf("33\n");
pthread_exit((void *)&rc);
}
Sorry, für den Haufen printf's, aber so sieht man wo der Fehler begraben liegt ;)