Ошибка сегментации (дамп ядра) в производителе и потребителе, использующем семафор - PullRequest
0 голосов
/ 25 сентября 2018

Я изучаю системное программирование в Linux, поэтому я просто попытался написать очень распространенную программу, которая является производителем и потребителем.Я использовал механизм семафоров для реализации своего кода.К сожалению, я получил ошибку сегментации , которую я действительно не мог найти, где я был не прав.Я надеюсь, что кто-то может помочь мне, спасибо.

Код следующим образом:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <semaphore.h>

sem_t sem_consumer;
sem_t sem_producer;

typedef struct node
{   
    int data;
    struct node *next;
} Node;

Node * head = NULL;

void * producer(void *arg)
{
    while (1)
    {
        sem_wait(&sem_producer);
        Node *ptr = (Node *)malloc(sizeof(Node));
        ptr->data = rand() % 1000;
        printf("++++++ producer: %lu, %d\n", pthread_self(), ptr->data);
        ptr->next = head;
        head = ptr;
        sem_post(&sem_consumer);
    }

    return NULL;
}

void * consumer(void * arg)
{
    while (1)
    {
        sem_wait(&sem_consumer);
        Node *pdel = head;
        head = head -> next;
        printf("------ consumer: %lu, %d\n", pthread_self(), pdel->data);
        free(pdel);
        sem_post(&sem_producer);
    }

    return NULL;
}

int main(int argc, char *argv[])
{
    sem_init(&sem_consumer, 0, 0);
    sem_init(&sem_producer, 0, 3);

    pthread_t pthid[2];

    pthread_create(&pthid[0], NULL, producer, NULL);
    pthread_create(&pthid[1], NULL, consumer, NULL);

    for (int i = 0; i < 2; i++)
    {
        pthread_join(pthid[i], NULL);
    }

    sem_destroy(&sem_consumer);
    sem_destroy(&sem_producer);

    return 0;
}

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

Я думаю, что главная проблема заключается в следующем:

  • У вас есть один ресурс - head
  • Вы " защищаете " его двумя отдельными семафорами- sem_producer и sem_consumer

Семафоры используются для сигнализации " вы можете взять что-то " или " вы можете положить что-то ", контролируяиспользование ресурсов - например, если вы хотите, чтобы список никогда не доходил глубже трех объектов.Это особенно важно, когда потоки производителя / потребителя имеют разное время выполнения.Если вы не слишком озабочены производством товаров, с которыми потребитель никогда не справится, вы можете полностью удалить sem_producer.

Мьютексы (" взаимное исключение ")используются для обеспечения того, чтобы два потока не обрабатывали один объект одновременно.Я бы посоветовал вам использовать мьютекс вокруг манипуляции с указателем вдоль семафоров.

pthread_mutex_t mux;
void *producer(void *arg) {
    while (1) {
        sem_wait(&sem_producer);

        /* gather data */

        pthread_mutex_lock(&mux);
        p_new->next = head;
        head = p_new;
        pthread_mutex_unlock(&mux);

        sem_post(&sem_consumer);
    }

    return NULL;
}
void *consumer(void *arg) {
    while (1) {
        sem_wait(&sem_consumer);

        pthread_mutex_lock(&mux);
        p_next = head;
        if (p_next != NULL) {
            head = p_next->next;
        }
        pthread_mutex_unlock(&mux);

        /* skip if there isn't actually a new item */
        if (p_next != NULL) {
            /* do processing and discard */
        }

        sem_post(&sem_producer);
    }

    return NULL;
}

Не забудьте позвонить pthread_mutex_init() и pthread_mutex_destroy().

0 голосов
/ 25 сентября 2018

sem_init(&sem_producer, 0, 3);

инициализирует семафор sem_producer равным 3, предоставляя потокам производителя и потребителя одновременный доступ к коду, например

ptr->next = head;
head = ptr;

и

Node *pdel = head;
head = head -> next;
printf("------ consumer: %lu, %d\n", pthread_self(), pdel->data);
free(pdel);

Ваш связанный список не защищен семафором должным образом.Это условие гонки.

Инициализация sem_producer в 1 исправит условие гонки:

sem_init(&sem_producer, 0, 1);

Могут быть и другие ошибки, которые я не обнаружил.

...