Question

I am learning to use forks. The task was to create simulation of warehouse's work. Producers (in an amount of argv[2]) create random number of "goods" (totally argv[1]), and consumers (in an amount of argv[3]) get random number of these goods. Below is the code for the program using threads. But I am trying to do the same using related proccesses (using fork()). 2nd version of the program doesn't work at all. Producers create 0 goods. I don't understand how to use fork properly. Should I somehow kill childs? Do they kill themselves after returning or continue to work till the end? Please help me to fix the second program. Second program:

#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/mman.h>
#define NBUFF 10
#define MAXNTHREADS 100
#define min( a, b ) ( ( a < b) ? a : b ) 
int nitems, nproducers, nconsumers; 

typedef struct shared_s
{ 
    int buff[NBUFF];
    int nput; 
    int nputval; 
    int nget;
    int ngetval; 
    sem_t mutex, nempty, nstored; 
} sharedtype;




int main(int argc, char **argv)
{
    sharedtype * shared;
    key_t key;
    int shmid, semid;
    int i, j, prodcount[MAXNTHREADS], conscount[MAXNTHREADS];

    shared = mmap(NULL, sizeof(sharedtype),
                PROT_READ | PROT_WRITE, MAP_SHARED, -1, 0);

    /* Wrong argv */
    if (argc != 4)
    {
        printf("usage: newconsumer <#items> <#producers> <#consumers>\n");
        exit(1);
    }
    nitems = atoi(argv[1]);
    nproducers = min(atoi(argv[2]), MAXNTHREADS);
    nconsumers = min(atoi(argv[3]), MAXNTHREADS);
    pid_t chpidpr [nproducers];
    pid_t chpidcon [nconsumers];
    /* initilising semaphores */
    sem_init(&(shared->mutex), 0, 1);
    sem_init(&(shared->nempty), 0, NBUFF);
    sem_init(&(shared->nstored), 0, 0);


    for (i = 0; i < nproducers; i++) {
        prodcount[i] = 0;
        switch (chpidpr[i] = fork())
        {
            case -1: 
                printf("fork error"); 
                return 1;
            case 0: 
                for (;;) 
                {
                    sem_wait(&shared->nempty); 
                    sem_wait(&shared->mutex);
                    if (shared->nput >= nitems) 
                    {
                        sem_post(&(shared->nstored));
                        sem_post(&(shared->nempty));
                        sem_post(&(shared->mutex));
                        return 0; 
                    }
                    shared->buff[(shared->nput) %NBUFF] = shared->nputval;
                    (shared->nput)++;
                    (shared->nputval)++;
                    sem_post(&(shared->mutex));
                    sem_post(&(shared->nstored));
                    prodcount[i] += 1;
                }
        }
    }
    for (i = 0; i < nproducers; i++) 
    {
        printf("producer count[%d] = %d\n", i, prodcount[i]);
    }
    for (i = 0; i < nconsumers; i++) {
        conscount[i] = 0;
        switch (chpidcon[i] = fork())
        {
            case -1: 
                printf("error"); 
                return 1;
            case 0: 
                for (;;) 
                {
                    sem_wait(&(shared->nstored)); 
                    sem_wait(&(shared->mutex));
                    if (shared->nget >= nitems) 
                    {
                        sem_post(&(shared->nstored));
                        sem_post(&(shared->mutex));
                        return 0;
                    }
                    j = shared->nget % NBUFF;
                    if (shared->buff[j] != shared->ngetval)
                    {
                        printf("error: buff[%d] = %d\n", j, shared->buff[j]);
                    }
                    shared->nget++;
                    shared->ngetval++;
                    sem_post(&(shared->mutex));
                    sem_post(&(shared->nempty)); 
                    conscount[i] += 1;
                }
        }
    }


    for (i = 0; i < nconsumers; i++) 
    {
        printf("consumer count[%d] = %d\n", i, conscount[i]);
    }
    /* destroying semaphores */
    sem_destroy(&(shared->mutex));
    sem_destroy(&(shared->nempty));
    sem_destroy(&(shared->nstored));
    exit(0);
}
Was it helpful?

Solution

It would be better if you could provide a minimal example of your code. So far the most obvious mistake that I can see is that your struct {/* .. */} shared is not in actual shared memory.

Threads have access to the same private memory, processes have their own private memory, that's why it's called private.

fork() creates cow copies of all memory that is not explicitly marked as shared. Allocate shared in shared memory would be the first thing to do.

mmap/MAP_SHARED is a good start for a program that creates new processes through fork.

struct shared_s {/* .. */} * shared;

int main() {
    shared = mmap(NULL, sizeof(struct shared_s)
                , PROT_READ | PROT_WRITE, MAP_SHARED, -1, 0);
    // ....
}

Also in case you are working on OS X you need to pass an additional flag MAP_HASSEMAPHORE in order for your semaphores to work correctly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top