Предоставить переменную состояния и мьютекс между процессами: нужно ли блокировать мьютекс раньше?

Мне нужно немного помочь понять, как использовать переменные условия в C для решения упражнения. Вот небольшой пример:

#include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #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; } } 

Проблема в том, что отец процесса продолжает блокироваться даже после передачи сигнала сыну. Все находится в общей памяти (с использованием shm_open и mmap ), поэтому условие должно быть одинаковым для обоих процессов. Может быть, я ошибаюсь, блокируя мьютексы, прежде чем вызывать ожидание или сигнал?

EDIT: Спасибо всем, кто мне помог. Вот правильный код с надписью CRITICAL:

 #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #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; } 

    Чтобы быть совместимым между процессами, мьютекс должен быть инициализирован соответствующим образом с помощью правильно инициализированного атрибута: http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setpshared.html

     #include  ... pthread_mutex_t * pmutex = NULL; pthread_mutexattr_t attrmutex; /* Initialise attribute to mutex. */ pthread_mutexattr_init(&attrmutex); pthread_mutexattr_setpshared(&attrmutex, PTHREAD_PROCESS_SHARED); /* Allocate memory to pmutex here. */ /* Initialise mutex. */ pthread_mutex_init(pmutex, &attrmutex); /* Use the mutex. */ /* Clean up. */ pthread_mutex_destroy(pmutex); pthread_mutexattr_destroy(&attrmutex); 

    (проверка ошибок оставлена ​​для удобства чтения этого примера)

    То же самое относится к переменной условия, которая должна быть разделена между процессами: http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setpshared.html

     #include  ... pthread_cond_t * pcond = NULL; pthread_condattr_t attrcond; /* Initialise attribute to condition. */ pthread_condattr_init(&attrcond); pthread_condattr_setpshared(&attrcond, PTHREAD_PROCESS_SHARED); /* Allocate memory to pcond here. */ /* Initialise condition. */ pthread_cond_init(pcond, &attrcond); /* Use the condition. */ /* Clean up. */ pthread_cond_destroy(pcond); pthread_condattr_destroy(&attrcond); 

    (проверка ошибок оставлена ​​для удобства чтения этого примера)


    Также см. Этот ответ: https://stackoverflow.com/a/2390670/694576

    В ожидании условия должно предшествовать оператор while, например:

     pthread_mutex_lock(mutex); while(!conditionSatisfied) pthread_cond_wait(condition, mutex); pthread_mutex_unlock(mutex); в pthread_mutex_lock(mutex); while(!conditionSatisfied) pthread_cond_wait(condition, mutex); pthread_mutex_unlock(mutex); 

    в то время как сигнализация должна выполняться следующим образом:

     pthread_mutex_lock(mutex); conditionSatisfied = true; pthread_cond_signal(condition); pthread_mutex_unlock(mutex); 

    да, мьютекс должен быть заблокирован до pthread_cond_wait , но не pthread_cond_signal для pthread_cond_signal . Если вы посмотрите на свой код, вы увидите, что мьютекс будет разблокирован дважды, что является признаком ошибки … также возможно, чтобы ребенок вызывал разблокировку на мьютексе, который был уничтожен родителем …

    Спящий Btw не гарантирует, что родитель выполнит сначала. Для этого вам понадобится … переменная состояния …

    Давайте будем гением компьютера.