0

Don't know why is consumer doing all the work?

I create a semaphor for the prodcut-consumer with an array of 10 integers, the array fills with names and it is return in ones and zeros (binary).The consumer is called even when the producer is unsing the semaphor.

Why does this happens?

This is the code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <fcntl.h>
#define SIZE 10
#define KEY 1234
int *Memory;
int i, j;
sem_t *sem;
char *name = "Hello";
int main(int argc, const char *argv[])
{
    int shmid;
    if ((shmid = shmget(KEY, sizeof(int) * SIZE, IPC_CREAT | S_IRWXU)) < 0)
    {
        perror("Error while creating shmget");
        return 1;
    }
    pid_t pid;
    sem = sem_open(name, O_CREAT, S_IRUSR | S_IWUSR, 1);
    if ((pid = fork()) != 0)
    {
        if ((shmid = shmget(KEY, sizeof(int) * SIZE, S_IRWXU)) < 0)
        {
            perror("error in shmget");
            return 1;
        }
        Memory = (int *)shmat(shmid, NULL, 0);
        if (Memory == NULL)
        {
            perror("error in shmat");
            return 1;
        }
        for (i = 0; i < 10; i++)
        {
            sem_wait(sem);
            Memory[j] = i;
            printf("Produced %i in box %i\n", i + 1, i + 1);
            sem_post(sem);
            sleep(1);
        }
        int status;
        wait(&status);
        sem_unlink(name);
        sem_destroy(sem);
        struct shmid_ds shmid_ds1;
        if (shmctl(shmid, IPC_RMID, &shmid_ds1) < 0)
        {
            perror(
                "Error in the father while executing shmctl when it was "
                "elimnating the segment of shared memory");
        }
    }
    else
    {
        if ((shmid = shmget(KEY, sizeof(int) * SIZE, S_IRWXU)) < 0)
        {
            perror("error in the producer with the shmget");
            return 1;
        }
        Memory = (int *)shmat(shmid, NULL, 0);
        if (Memory == NULL)
        {
            perror("error in the producer with the  shmat");
            return 1;
        }
        for (i = 0; i < 10; i++)
        {
            sem_wait(sem);
            Memory[i] = -1;
            printf("Consume and now it is %i in box %i\n", Memory[i], i + 1);
            sem_post(sem);
        }
    }
    return 0;
}

And the output is:

Produced 1 in box 1
Consume and now it is -1 in box 1
Consume and now it is -1 in box 2
Consume and now it is -1 in box 3
Consume and now it is -1 in box 4
Consume and now it is -1 in box 5
Consume and now it is -1 in box 6
Consume and now it is -1 in box 7
Consume and now it is -1 in box 8
Consume and now it is -1 in box 9
Consume and now it is -1 in box 10
Produced 2 in box 2
Produced 3 in box 3
Produced 4 in box 4
Produced 5 in box 5
Produced 6 in box 6
Produced 7 in box 7
Produced 8 in box 8
Produced 9 in box 9
Produced 10 in box 10
user2485710
  • 9,451
  • 13
  • 58
  • 102
user3606231
  • 11
  • 1
  • 1

2 Answers2

1
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
const int max = 5;
int arr[5], f = 0, r = -1;
sem_t s1, s2, sm;
void* eprod(void* pv)
{
    int i, x;
    printf("Producer Welcome\n");
    // sleep(10);
    while (1)
    {
        x = rand() % 100;
        printf("producer going to add:%d\n", x);
        sem_wait(&s2);
        sem_wait(&sm);
        // down s2 //buffer may be full
        // lock sm
        r = (r + 1) % max;
        arr[r] = x;
        sem_post(&sm);
        sem_post(&s1);
        sleep(10);
    }
    // unlock sm
    // up s1
}
void* econs(void* pv)
{
    int i, x;
    printf("Consumer Welcome\n");
    while (1)
    {
        sem_wait(&s1);
        sem_wait(&sm);
        // down s1
        // lock sm
        x = arr[f];
        f = (f + 1) % max;
        printf("Consumer removed element:%d\n", x);
        sem_post(&sm);
        sem_post(&s2);
        // unlock sm
        // up s2
        // sleep(5);
    }
}
int main()
{
    pthread_t pt1, pt2;
    sem_init(&s1, 0, 0);    // 3rd Parameter ival=1
    sem_init(&s2, 0, max);  // 3rd Parameter ival=1
    sem_init(&sm, 0, 1);    // 3rd Parameter ival=1
    pthread_create(&pt1, NULL, eprod, (void*)0);
    pthread_create(&pt2, NULL, econs, (void*)1);
    printf("Main Thread is Running\n");
    pthread_join(pt1, NULL);
    pthread_join(pt2, NULL);
    printf("Main -- - - Thanks..!\n");
    return 0;
}

Hope this helps..

user2485710
  • 9,451
  • 13
  • 58
  • 102
Rohit Gaur
  • 23
  • 4
  • Thank you @user2485710 I already use threads to solee the problem, and work perfectly. But do you know how could I solve consumer-produce with semaphores and forks? – user3606231 May 06 '14 at 21:17
  • @user3606231 the name of the right is the one for the user that made the post, I just edited it to fix the indentation . – user2485710 May 07 '14 at 01:44
0

Your output is consistent with your program code. Both of your processes use the semaphore to gain access to the shared memory block, so they work by mutual exclusion, i.e. only one of them is allowed to use the Memory[] array at any given time.

But there is nothing in your program that would constrain the behaviour of the processes further, so it is possible for the consumer to proceed without the producer doing anything.

You need to introduce more bookkeping into your program to handle reserved/free slots in the Memory[] array, and two more semaphores for synchronising the progress of the producer and consumer. See any standard solution to the problem, e.g. http://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem#Using_semaphores

xxa
  • 1,258
  • 9
  • 20