I have an assignment to implement Producer consumer problem in a convoluted way(may be to test my understanding). The parent process should set up a shared memory. The unnamed semaphores(for empty count and filled count) should be initialized and a mutex should be initialized. Then two child processes are created, a producer child and a consumer child. Each child process should create a new thread which should do the job.

PS: I have read that the semaphore's should be kept in a shared memory as they would be shared by different processes.

Please provide some hints, or suggest changes.

So far, I have done this:

struct shmarea 
{
unsigned short int read;
unsigned short int max_size;
char scratch[3][50];
unsigned short int write;
sem_t sem1;// Empty slot semaphore
sem_t sem2;// Filled slot Semaphore
}; 

void *thread_read(void* args);
void *thread_write(void *args);

pthread_mutex_t work_mutex;

struct shmarea *shma;

int main()
{
int fork_value,i=0,shmid;
printf("Parent process id is %d\n\n",getpid());
int res1,res2;
key_t key;
char *path = "/tmp";
int id = 'S';

key = ftok(path, id);
shmid =  shmget(key,getpagesize(),IPC_CREAT|0666);

printf("Parent:Shared Memory id = %d\n",id);
shma = shmat(shmid,0,0);    

shma->read = 0;
shma->max_size = 3;
shma->write = 0; 

pthread_t a_thread;
pthread_t b_thread;

void *thread_result1,*thread_result2;

res1 = sem_init(&(shma->sem1),1,3);//Initializing empty slot sempahore
res2 = sem_init(&(shma->sem2),1,0);//Initializing filled slot sempahore

res1 = pthread_mutex_init(&work_mutex,NULL);

while(i<2)
{
    fork_value = fork();
    if(fork_value > 0)
    {
        i++;
    }
    if(fork_value == 0)
    {
        if(i==0)
        {           
            printf("***0***\n");
            //sem_t sem1temp = shma->sem1;
            char ch;int res;
            res= pthread_create(&a_thread,NULL,thread_write,NULL);
        }
        if(i==1)
        {
            printf("***1***\n");        
            //sem_t sem2temp = shma->sem2;      
            int res;
            char ch;
            res= pthread_create(&b_thread,NULL,thread_read,NULL);
        }
    }
}
int wait_V,status;
res1 = pthread_join(a_thread,&thread_result1);
res2 = pthread_join(b_thread,&thread_result2);
}

void *thread_read(void *args)
{   
    while(1)
    {
        sem_wait(&(shma->sem2));
        pthread_mutex_lock(&work_mutex);
        printf("The buf read from consumer:%s\n",shma->scratch[shma->read]);
        shma->read = (shma->read+1)%shma->max_size;             
        pthread_mutex_unlock(&work_mutex);
        sem_post(&(shma->sem1));
    }
} 

void *thread_write(void *args)
{
    char buf[50];
    while(1)
    {
        sem_wait(&(shma->sem1));    
        pthread_mutex_lock(&work_mutex);
        read(STDIN_FILENO,buf,sizeof(buf)); 
        strcpy(shma->scratch[shma->write],buf);
        shma->write = (shma->write+1)%shma->max_size;               
        pthread_mutex_unlock(&work_mutex);
        sem_post(&(shma->sem2));
    }
} 
有帮助吗?

解决方案

(1) Your biggest problem by far is that you have managed to write a fork bomb. Because you don't exit either child in the fork loop each child is going to fall through and loop around and create their own children until you crash or bring the system down. You want something more like this:

while(i < 2)
{
    fork_value = fork();

    if(fork_value > 0)
        i++;

    if(fork_value == 0)
    {
        if(i==0)
        {
            printf("0 child is pid %d\n", getpid());

            int res;
            res = pthread_create(&a_thread,NULL,thread_write,NULL);
            res = pthread_join(a_thread,&thread_result1);
            exit(0);
        }

        if(i==1)
        {
            printf("1 child is pid %d\n", getpid());

            int res;
            res = pthread_create(&b_thread,NULL,thread_read,NULL);
            res = pthread_join(b_thread,&thread_result2);
            exit(0);
        }
    }
}

for (i = 0; i < 2; ++i)
    wait(NULL);

Notice the wait on the children which you neglected.

(2) Always check your return codes. They are like safety belts, a bit of a drag but so helpful when you crash. (Yes, I didn't take my advice here but you should.)

(3) These names are awful.

unsigned short int read;
unsigned short int write;

Stay away from naming variables after system calls. It's confusing and just asking for trouble.

(4) Terminology wise, processes with a common ancestor, like these, are related. The parent can open shared memory and other resources and pass it on to the children. Unrelated processes would, for example, multiple instances of program launched from different terminals. They can share resources but not in the "inherited" way forked processes do.

It's late and didn't get around to looking at what you are doing with the threads and such but this should get you started.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top