Ich brauche etwas Hilfe, um zu verstehen, wie Bedingungsvariablen in C verwendet werden, um eine Übung zu lösen. Hier ein kleines Beispiel:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#define OKTOWRITE "/oktowrite"
#define MESSAGE "/message"
#define MUTEX "/lock"
int main(int argc, char** argv)
{
pthread_cond_t* condition;
pthread_mutex_t *mutex;
char* message;
int des_cond, des_msg, des_mutex;
int mode = S_IRWXU | S_IRWXG;
des_mutex = shm_open(MUTEX, O_CREAT | O_RDWR | O_TRUNC, mode);
if (des_mutex < 0)
{
perror("failure on shm_open on des_mutex");
exit(1);
}
if (ftruncate(des_mutex, sizeof(pthread_mutex_t)) == -1)
{
perror("Error on ftruncate to sizeof pthread_cond_t\n");
exit(-1);
}
mutex = (pthread_mutex_t*) mmap(NULL, sizeof(pthread_mutex_t),
PROT_READ | PROT_WRITE, MAP_SHARED, des_mutex, 0);
if (mutex == MAP_FAILED )
{
perror("Error on mmap on mutex\n");
exit(1);
}
pthread_mutex_init(mutex, NULL );
des_cond = shm_open(OKTOWRITE, O_CREAT | O_RDWR | O_TRUNC, mode);
if (des_cond < 0)
{
perror("failure on shm_open on des_cond");
exit(1);
}
if (ftruncate(des_cond, sizeof(pthread_cond_t)) == -1)
{
perror("Error on ftruncate to sizeof pthread_cond_t\n");
exit(-1);
}
condition = (pthread_cond_t*) mmap(NULL, sizeof(pthread_cond_t),
PROT_READ | PROT_WRITE, MAP_SHARED, des_cond, 0);
if (condition == MAP_FAILED )
{
perror("Error on mmap on condition\n");
exit(1);
}
pthread_cond_init(condition, NULL );
if (!fork())
{
sleep(3);
pthread_mutex_lock(mutex);
pthread_cond_signal(condition);
pthread_mutex_unlock(mutex);
printf("son signaled\n");
exit(0);
}
else
{
printf("wait on condition\n");
pthread_mutex_lock(mutex);
pthread_cond_wait(condition, mutex);
pthread_mutex_unlock(mutex);
printf("Signaled by son process, wake up\n");
pthread_mutex_destroy(mutex);
pthread_cond_destroy(condition);
shm_unlink(OKTOWRITE);
shm_unlink(MESSAGE);
shm_unlink(MUTEX);
return 0;
}
}
Das Problem ist, dass der Vater des Prozesses weiterhin gesperrt wird, auch nach der Signalisierung des Sohnes. Alles befindet sich im gemeinsamen Speicher (mithilfe von shm_open
und mmap
), also sollte die Bedingung für beide Prozesse gleich sein. Mache ich vielleicht einen Fehler, indem ich den Mutex sperre, bevor ich wait oder signal anrufe?
EDIT: Danke an alle die mir geholfen haben. Hier ist der richtige Code mit den markierten KRITISCHEN Teilen:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#define OKTOWRITE "/condwrite"
#define MESSAGE "/msg"
#define MUTEX "/mutex_lock"
int main(int argc, char** argv) {
pthread_cond_t* condition;
pthread_mutex_t* mutex;
char* message;
int des_cond, des_msg, des_mutex;
int mode = S_IRWXU | S_IRWXG;
des_mutex = shm_open(MUTEX, O_CREAT | O_RDWR | O_TRUNC, mode);
if (des_mutex < 0) {
perror("failure on shm_open on des_mutex");
exit(1);
}
if (ftruncate(des_mutex, sizeof(pthread_mutex_t)) == -1) {
perror("Error on ftruncate to sizeof pthread_cond_t\n");
exit(-1);
}
mutex = (pthread_mutex_t*) mmap(NULL, sizeof(pthread_mutex_t),
PROT_READ | PROT_WRITE, MAP_SHARED, des_mutex, 0);
if (mutex == MAP_FAILED ) {
perror("Error on mmap on mutex\n");
exit(1);
}
des_cond = shm_open(OKTOWRITE, O_CREAT | O_RDWR | O_TRUNC, mode);
if (des_cond < 0) {
perror("failure on shm_open on des_cond");
exit(1);
}
if (ftruncate(des_cond, sizeof(pthread_cond_t)) == -1) {
perror("Error on ftruncate to sizeof pthread_cond_t\n");
exit(-1);
}
condition = (pthread_cond_t*) mmap(NULL, sizeof(pthread_cond_t),
PROT_READ | PROT_WRITE, MAP_SHARED, des_cond, 0);
if (condition == MAP_FAILED ) {
perror("Error on mmap on condition\n");
exit(1);
}
/* HERE WE GO */
/**************************************/
/* set mutex shared between processes */
pthread_mutexattr_t mutexAttr;
pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(mutex, &mutexAttr);
/* set condition shared between processes */
pthread_condattr_t condAttr;
pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(condition, &condAttr);
/*************************************/
if (!fork()) {
sleep(10);
pthread_mutex_lock(mutex);
pthread_cond_signal(condition);
printf("son signaled\n");
pthread_mutex_unlock(mutex);
exit(0);
}
else {
printf("father waits on condition\n");
pthread_mutex_lock(mutex);
pthread_cond_wait(condition, mutex);
pthread_mutex_unlock(mutex);
printf("Signaled by son process, wake up!!!!!!!!\n");
pthread_condattr_destroy(&condAttr);
pthread_mutexattr_destroy(&mutexAttr);
pthread_mutex_destroy(mutex);
pthread_cond_destroy(condition);
shm_unlink(OKTOWRITE);
shm_unlink(MESSAGE);
shm_unlink(MUTEX);
}
return 0;
}
mögliches Duplikat von Funktionieren pthread Mutexs über Threads hinweg, wenn sie sich im gemeinsamen Speicher befinden?
– alk
2. Dezember 2013 um 10:49 Uhr
Setzen Sie auch das Attribut für die gemeinsam zu nutzenden Bedingungsvariablen. Bitte beachten Sie auch meine Antwort.
– alk
2. Dezember 2013 um 11:07 Uhr
Ich habe meinen Kommentar zum alten/neuen Code geschrieben, bevor Sie Ihr Update angewendet haben. Für die Fehlerprüfung habe ich auf die verwiesen
pthread_*
Anrufe sowiefork()
. Jeder Anruf, der so definiert ist, dass er fehlschlagen kann, schlägt einen Tag früher oder später fehl. Von diesen würde ich zumindest die testrelevanten in Betracht ziehen, bei denen ich unbrauchbare Daten hinterlassen kann, wenn sie fehlschlagen.– alk
2. Dezember 2013 um 13:29 Uhr
Ich habe keinen Punkt oben bekommen. (Nehmen wir an) Wir greifen zuerst die gemeinsam genutzte Mutex-Sperre im übergeordneten Prozess und warten auf eine Bedingung, die vom untergeordneten Prozess signalisiert werden soll. Der untergeordnete Prozess muss jedoch diesen Mutex haben (bevor die Bedingung signalisiert wird), der bereits vom übergeordneten Prozess gehalten wird. Also, ich verstehe nicht, wie Deadlock hier nicht passiert. Kann mir das bitte jemand erklären?
– stdout
28. März 2017 um 19:12 Uhr
Egal. Ich habe meine Antwort gefunden. “pthread_cond_wait gibt den Mutex frei und wartet, bis die Bedingung cond_t signalisiert wird”.
– stdout
28. März 2017 um 19:25 Uhr