Невозможно отправить сигнал с помощью pthread_cond_signal другому процессу в C

Я пытаюсь реализовать проблему производителя-потребителя, используя сценарий с двумя процессами.

Процесс1 — Производитель, а Процесс2 — Потребитель. Процесс-потребитель ожидает переменной условия (pthread_cond_wait(cond)), и производитель отправит сигнал потребителю через pthread_cond_signal(cond).

Я прошел по этим ссылкам общий мьютекс и переменная условия в процессе pthread_mutexattr_setpshared</ a> везде было сказано, что можно использовать мьютекс и условную переменную в нескольких процессах,

pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);

В этой ссылке

общие мьютексы В качестве рекомендации void было сказано проверить, поддерживает ли моя система или нет? Я проверил и получил 200809 в качестве возвращаемого значения sysconf(_SC_THREAD_PROCESS_SHARED), что означает, что моя система поддерживает PTHREAD_PROCESS_SHARED.

Я пытаюсь отправить pthread_cond_signal от производителя (процесс-1) потребителю (процесс-2). И производитель, и потребитель используют одну и ту же инициализированную переменную мьютекса/условия.

Однако потребитель не получает сигнал. Похоже, либо сигнал не отправляется, либо он потерян.

Где я делаю ошибки? Я использую Ubuntu, gcc-4.6.3.

Вот мой код.

Производитель.с:

    #include <pthread.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <sys/wait.h>
    #include <pthread.h>
    #include <sched.h>
    #include <syscall.h>
    #include <sys/stat.h>
    #include <errno.h>
    #include <sys/mman.h>
    #include <fcntl.h>
    #include <stdbool.h>

    pthread_cond_t* condition;
    pthread_mutex_t* mutex;

    #define OKTOWRITE "/oktowrite"
    #define MESSAGE "/message"
    #define MUTEX "/lock"


    struct shared_use_st 
    {
    bool conditionSatisfied;
    };

    struct shared_use_st *shared_stuff;

    void create_shared_memory()
    {
        int shmid;
        void *shared_memory=(void *)0;
        shmid =shmget( (key_t)1234, 4096, 0666 | IPC_CREAT );

        if (shmid == -1)
        {
            fprintf(stderr,"shmget failed\n");
            exit(EXIT_FAILURE);
        }

        shared_memory =shmat(shmid, (void *)0,0);

        if(shared_memory == (void *)-1)
        {
            fprintf(stderr,"shmat failed\n");
            exit(EXIT_FAILURE); 
        }

        shared_stuff = (struct shared_use_st *)shared_memory;
    }


    int main()
    {
        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);
        }

        /* set mutex shared between processes */
        pthread_mutexattr_t mutexAttr;
        pthread_mutexattr_init(&mutexAttr);
        pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
        pthread_mutex_init(mutex, &mutexAttr);

        /* set condition shared between processes */
        pthread_condattr_t condAttr;
        pthread_condattr_init(&condAttr);
        pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
        pthread_cond_init(condition, &condAttr);

        create_shared_memory();
        shared_stuff->conditionSatisfied=0;

        int count=0;
        while(count++<10)
        {
            pthread_mutex_lock(mutex);
            shared_stuff->conditionSatisfied=1;
            pthread_mutex_unlock(mutex);

            pthread_cond_signal(condition);
            printf("signal sent to consumer, %d\n",count);

            sleep(3);
        }

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

Потребитель.c:

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sched.h>
#include <syscall.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdbool.h>

pthread_cond_t* condition;
pthread_mutex_t* mutex;

#define OKTOWRITE "/oktowrite"
#define MESSAGE "/message"
#define MUTEX "/lock"

struct shared_use_st 
{
bool conditionSatisfied;
};

struct shared_use_st *shared_stuff;

void create_shared_memory()
{
    int shmid;
    void *shared_memory=(void *)0;
    shmid =shmget( (key_t)1234, 4096, 0666 | IPC_CREAT );

    if (shmid == -1)
    {
        fprintf(stderr,"shmget failed\n");
        exit(EXIT_FAILURE);
    }

    shared_memory =shmat(shmid, (void *)0,0);

    if(shared_memory == (void *)-1)
    {
        fprintf(stderr,"shmat failed\n");
        exit(EXIT_FAILURE); 
    }

    shared_stuff = (struct shared_use_st *)shared_memory;
}

int main()
{
    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);
    }

    /* set mutex shared between processes */
    pthread_mutexattr_t mutexAttr;
    pthread_mutexattr_init(&mutexAttr);
    pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
    pthread_mutex_init(mutex, &mutexAttr);

    /* set condition shared between processes */
    pthread_condattr_t condAttr;
    pthread_condattr_init(&condAttr);
    pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
    pthread_cond_init(condition, &condAttr);

    create_shared_memory();
    shared_stuff->conditionSatisfied=0;

    while(1)
    {
        printf("Receiver waits on for signal from hello1.c \n");

        pthread_mutex_lock(mutex);
        while(!shared_stuff->conditionSatisfied)
            pthread_cond_wait(condition, mutex);
        pthread_mutex_unlock(mutex);

        printf("Signal received, wake up!!!!!!!!\n");

        //reset
        pthread_mutex_lock(mutex);
        shared_stuff->conditionSatisfied=0;
        pthread_mutex_unlock(mutex);
    }

}

Мне кажется, что вы неправильно используете разделяемую память: вы вызываете в обоих процессах shm_open с O_CREATE, а также ftruncate. Только один процесс должен создать сегмент разделяемой памяти и изменить его размер. Другой должен прикрепиться к нему.   —  person bholanath    schedule 18.01.2016

См. также:  Запрос Firebase ничего не возвращает

Вы пытались поделиться чем-то между двумя процессами, прежде чем работать с мьютексом?   —  person bholanath    schedule 18.01.2016

@terencehill, AFIK, другой процесс сначала проверит, существует ли уже общая память или нет. Если он уже есть, он не создаст новый, а только присоединится к существующему.   —  person bholanath    schedule 18.01.2016

@terencehill, проблема в том, что обновленное значение conditionSatisfied не отображается в потребительском процессе.   —  person bholanath    schedule 18.01.2016

В каком порядке происходят события? Вы усекаете как производителя, так и потребителя.   —  person bholanath    schedule 18.01.2016

Более того, вы смешиваете старый shmget/shmat с sum_open, что меня немного сбивает с толку.   —  person bholanath    schedule 18.01.2016

проблема заключается в том, что обновленное значение conditionSatisfied не отображается в процессе потребителя. Посмотрите на сгенерированные инструкции и убедитесь, что проверка не была оптимизирована. Вы также можете добавить некоторый код для отправки чего-либо в stderr в цикле потребителя while, чтобы убедиться, что потребитель получает сигнал.   —  person bholanath    schedule 18.01.2016

@terencehill Кроме того, сигнал также не отправляется потребителю. Если я удалю предикат, то while(!shared_stuff-›conditionSatisfied) все равно потребитель не проснется.   —  person bholanath    schedule 18.01.2016

@AndrewHenle Я тебя не понял. Я уже использовал gcc -O0 для отключения всей оптимизации.   —  person bholanath    schedule 18.01.2016

@terencehill, сначала я запускаю потребителя, поэтому он ждет сигнала от производителя, затем я запускаю производителя.   —  person bholanath    schedule 18.01.2016

Итак, усечение в производителе бессмысленно, но не должно быть проблемой.   —  person bholanath    schedule 18.01.2016

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. bholanath

    Мьютекс, совместно используемый процессами, должен быть инициализирован только одним из них

    Ошибка заключается в том, что вы инициализируете мьютекс и условие в обоих процессах. Однако, поскольку они являются общими, их следует инициализировать только на потребителе.

    Я также предлагаю не смешивать старые функции System V shmget/shmat с новыми shm_open POSIX.

    Я определил новое общее целое число shint, которое указывает на общую память, инициализированную с помощью shm_open и присоединенную через mmap. shint используется как флаг для ожидания условия pthread.

    На мой взгляд, производитель, который запускается после потребителя, не нуждается в усечении сегмента памяти и может открыть общую память только с O_RDWR. Сначала производитель берет блокировку и устанавливает shint в 1.

    С другой стороны, потребитель, который запускается первым, должен создать сегменты общей памяти и изменить их размер с помощью ftruncate. Он также устанавливает общий флаг shint в 0 и ожидает его. Кроме того, перед вызовом shm_open лучше развязать (через shm_unlik) все используемые сегменты общей памяти, чтобы убрать возможные ошибки при предыдущих вызовах (например, если перед развязкой произошел сбой кода).

    Я перенес инициализацию атрибутов мьютекса и условия в начало, потому что это кажется более понятным и правильным.


    Producer.c

    int main()
    {
        int des_cond, des_msg, des_mutex;
        int mode = S_IRWXU | S_IRWXG;
    
        /* set mutex shared between processes */
        pthread_mutexattr_t mutexAttr;
        pthread_mutexattr_init(&mutexAttr);
        pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
    
        /* set condition shared between processes */
        pthread_condattr_t condAttr;
        pthread_condattr_init(&condAttr);
        pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
    
        des_mutex = shm_open(MUTEX, O_RDWR, mode);
    
        if (des_mutex < 0) {
            perror("failure on shm_open on des_mutex");
            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_RDWR, mode);
    
        if (des_cond < 0) {
            perror("failure on shm_open on des_cond");
            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);
        }
    
        int fd = shm_open(MESSAGE, O_RDWR, 0644);
        if (fd < 0) {
            perror("failure on shm_open on fd");
            exit(1);
        }
    
        if(ftruncate(fd, sizeof(int)) == -1) {
            perror("Error on ftruncate to sizeof ftruncate fd\n");
            exit(-1);
        }
    
        int *shint;
        shint = (int *) mmap(NULL, sizeof(int), PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
    
        if (shint == MAP_FAILED ) {
            perror("Error on mmap on shint\n");
            exit(1);
        }
    
    
        // set ot 0
        *shint = 0;
    
    
        int count=0;
        while(count++<10)
        {
            pthread_mutex_lock(mutex);
            *shint = 1;
            pthread_mutex_unlock(mutex);
    
            pthread_cond_signal(condition);
            printf("signal sent to consumer, %d\n",count);
    
            sleep(3);
        }
    
        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;
    }
    

    Потребитель.c

    int main()
    {
        int des_cond, des_msg, des_mutex;
        int mode = S_IRWXU | S_IRWXG;
    
        // Unlink first to clean  
        shm_unlink(MUTEX);
        shm_unlink(OKTOWRITE);
        shm_unlink(MESSAGE);
    
        pthread_mutexattr_t mutexAttr;
        pthread_mutexattr_init(&mutexAttr);
        pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
    
        pthread_condattr_t condAttr;
        pthread_condattr_init(&condAttr);
        pthread_condattr_setpshared(&condAttr, PTHREAD_PROCESS_SHARED);
    
    
        des_mutex = shm_open(MUTEX, O_CREAT | O_RDWR, 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, 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);
        }
    
        int fd = shm_open(MESSAGE, O_CREAT|O_RDWR, 0644);
        if (fd < 0) {
            perror("failure on shm_open on fd");
            exit(1);
        }
    
        if(ftruncate(fd, 16) == -1) {
            perror("Error on ftruncate to sizeof ftruncate fd\n");
            exit(-1);
        }
        int *shint;
        shint = (int *) mmap(NULL, sizeof(int), PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
    
        if (shint == MAP_FAILED ) {
            perror("Error on mmap on shint\n");
            exit(1);
        }
    
    
        *shint = 0;
    
            if (pthread_mutex_init(mutex, &mutexAttr) != 0)    {printf("Error initi mutex"); exit(111);}
            if (pthread_cond_init(condition, &condAttr) != 0) {printf("Error initi cond");  exit(111);}
    
        while(1)
        {
            printf("Receiver waits on for signal from hello1.c \n");
    
            pthread_mutex_lock(mutex);
            while(shint == 0)
                pthread_cond_wait(condition, mutex);
            printf("Waiting"); sleep(1);
            pthread_mutex_unlock(mutex);
    
            printf("Signal received, wake up!!!!!!!!\n");
    
            break;
            //reset
            pthread_mutex_lock(mutex);
            shared_stuff->conditionSatisfied=0;
            pthread_mutex_unlock(mutex);
        }
    
        return 0;
    }
    

    спасибо, он отлично работает для отправки сигнала от производителя к потребителю. Я хочу отправлять данные от производителя к потребителю, поэтому я использовал общую память. Что вы предлагаете для отправки данных? Должен ли я просто создать общую память, используя shm_open, только что вы сделали shint int memory? person bholanath; 18.01.2016

    Это зависит от того, чего вы пытаетесь достичь. Лично я бы остановился на разделяемой памяти: вы можете реализовать почти все типы коммуникаций, просто используя правильные механизмы синхронизации и расположение данных в разделяемой памяти. person bholanath; 18.01.2016

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: