0

I write a program containing two processes: the first one contains a group of two semaphores and creates the child process that reads all data in the shared memory segment and prints them.

In the second one, the child process computes the data using a compute function that returns 0 when all data are computed. It transmits them to the parent through the shared memory segment.

To write data:

  • On the 1st semaphore the child makes P and the parent make V.

  • On the 2nd semaphore the child makes V and the parent make P.

But as I'm new in this topic and still getting hardness to understand, it seems like I'm doing something wrong because it's not working as it has to be.

Here is my code:

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <fcntl.h> #include <semaphore.h> #include <sys/shm.h> #include <errno.h> #include <sys/wait.h> int sum =0; int compute(int data){ sum += data; return sum; } int main(){ int i; int shm_id; int data; pid_t pid; key_t shm_key; sem_t *sem; // unsigned int sem_value =2; shm_key = ftok("/dev/null", 65); shm_id = shmget(shm_id, sizeof(int), 0644 | IPC_CREAT); if (shm_id < 0){ perror("shmgget"); exit(EXIT_FAILURE); } // data = shmat(shm_id, NULL, 0); sem = sem_open("semaphore", O_CREAT | O_EXCL, 0644, 2); for (i = 0; i < 2; i++){ pid = fork(); if (pid < 0) { perror("fork"); sem_unlink("semaphore"); sem_close(sem); exit(EXIT_FAILURE); } else if (pid == 0) { break; } } if (pid == 0) { puts("Enter the data:"); scanf("%d", &data); //child process sem_wait(sem); printf("Child - %d is in critical section\n", i); sleep(1); puts("Enter the data:"); scanf("%d", &data); // *shrd_value += data; printf("Child - %d: new value of data = %d\n", i, data); printf("Child - %d: sum of whole data by far = %d\n", i, compute(data)); sem_post(sem); exit(EXIT_SUCCESS); } else if (pid > 0) { //parent process while (pid = waitpid(-1, NULL, 0)) { if (errno == ECHILD) { break; } } puts("All children exited"); shmdt(&data); shmctl(shm_id, IPC_RMID, 0); sem_unlink("semaphore"); sem_close(sem); exit(0); } } 

Output:

Enter the data: Enter the data: 2 Child - 0 is in critical section 1Enter the data: Child - 1 is in critical section Enter the data: 3 Child - 0: new value of data = 3 Child - 0: sum of whole data by far = 3 2 Child - 1: new value of data = 2 Child - 1: sum of whole data by far = 2 All children exited 

2 Answers 2

1

I have also modified the way they write to shared memory: they write directly at the address given by shmat call that is missing in your code. I have fixed some bugs and simplifed the code (removed the array - added detailed logging especially before and after entering the critial section):

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <fcntl.h> #include <semaphore.h> #include <sys/shm.h> #include <errno.h> #include <sys/wait.h> int main(){ int i; int shm_id; pid_t pid; int *addr; int data; pid_t current_pid; key_t shm_key; sem_t *sem; shm_key = ftok("/dev/null", 65); shm_id = shmget(shm_key, sizeof(int), 0644 | IPC_CREAT); if (shm_id < 0){ perror("shmget"); exit(EXIT_FAILURE); } sem_unlink("semaphore"); sem = sem_open("semaphore", O_CREAT, 0644, 1); if (sem == SEM_FAILED) { perror("sem_open"); exit(EXIT_FAILURE); } addr = (int *) shmat(shm_id, (void *) 0, 0); if (addr == (void *) -1) { perror("shmat"); exit(EXIT_FAILURE); } *addr = 0; for (i = 0; i < 2; i++){ pid = fork(); if (pid < 0) { perror("fork"); sem_close(sem); sem_unlink("semaphore"); exit(EXIT_FAILURE); } } if (pid == 0) { current_pid = getpid(); printf("Child %d: waiting for critical section \n", current_pid); sem_wait(sem); printf("Child %d: enters in critical section \n", current_pid); printf("child %d: Enter the data:\n", current_pid); scanf("%d", &data); printf("Child %d: new value of data = %d\n", current_pid, data); printf("Child %d: sum of whole data so far = %d\n", current_pid, *addr += data); sem_post(sem); printf("Child %d exits from critical section\n", current_pid); exit(EXIT_SUCCESS); } else if (pid > 0) { //parent process while (pid = waitpid(-1, NULL, 0)) { if (errno == ECHILD) { break; } } puts("All children exited"); shmdt(addr); shmctl(shm_id, IPC_RMID, 0); sem_close(sem); sem_unlink("semaphore"); exit(0); } exit(0); } 

Note that semaphore initial value must be 1 to have a true critical section for 2 processes.

I have also removed the sleep calls and we can see that one of the process is waiting:

Child 22514: waiting for critical section Child 22514: enters in critical section child 22514: Enter the data: Child 22515: waiting for critical section 333 Child 22514: new value of data = 333 Child 22514: sum of whole data so far = 333 Child 22514 exits from critical section Child 22515: enters in critical section child 22515: Enter the data: 666 Child 22515: new value of data = 666 Child 22515: sum of whole data so far = 999 Child 22515 exits from critical section All children exited All children exited 
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks a lot, I compared both code and understood the parts i missed and done mistake. Well, how about consumer and producer issue in this code? like, while the producer value set to the shared memory and consumer dont take any value and returns the 1st value from shared memory. if no value is avaiable then it will wait the program wait the producer store thevalue. How can i link it?
IMO this is is a very simplified producer/consumer system: ok the child processes are the producer and the parent process is the consumer but in this code it does not do anything with the data.: it does not really consume it and because it knows that the child processes have exited it can read the data without semaphores. In a usual producer/consumer system we would have daemons processes (parent and child) always running with continuous data processing between child and parent.
Well, okay. I've tried to do the program from scratch, not related to this one, but it didn't work properly though it has no error sign. Can I Show it? While trying to learn that topic (consumer/producer), I got hardness ugh.
Yes you can show it and I will try to have a look this week-end.
Thanks a lot! I'm going to post it on answer section.
0

Here's the code with producer and consumer process

#include <stdio.h> #include <stdlib.h> #include <fcntl.h> // O_CREAT, O_EXEC #include <errno.h> // errno, ECHILD #include <unistd.h> #include <sys/shm.h> // shmat(), IPC_RMID #include <sys/wait.h> #include <semaphore.h> // sem_open(), sem_destroy(), sem_wait()... #include <sys/types.h> // key_t, sem_t, pid_t #include <pthread.h> #define BUFF 10 typedef struct data{ int buff[BUFF]; int size; int index; }DATA; int main(int argc, char const *argv[]) { sem_t *full, *empty, *access; key_t shm_key; int shm_id; full = sem_open ("fullname", O_CREAT , 0644, 15); empty = sem_open ("empty", O_CREAT , 0644, 0); access = sem_open ("access", O_CREAT , 0644, 1); if (argc!=2) { exit(1); } int value=atoi(argv[1]); //initialize a shared variable in shared memory shm_key = ftok("/dev/null", 60); shm_id = shmget(shm_key, sizeof(DATA), 0); // shared memory error check if (shm_id < 0){ shm_id = shmget(shm_key, sizeof(DATA), 0644 | IPC_CREAT); DATA *data = (DATA*) shmat (shm_id, NULL, 0); data->size=0; data->index=0; //index } printf("Shared memory id: %d\n",shm_id ); printf("Checking buffer...,\n"); //If in the buffer have free space then will wait for consumer to consume the data\n" sem_wait(empty); printf("\nLocking buffer to produce data\n"); sem_wait(access); //initialize a shared variable in shared memory shm_key = ftok("/dev/null", 60); shm_id = shmget(shm_id, sizeof(DATA), 0644 | IPC_CREAT); // shared memory error check if (shm_id < 0){ perror("semaphore"); exit(EXIT_FAILURE); } //Shared variable DATA *data = (DATA*) shmat (shm_id, NULL, 0); int index=(data->size + data->index) % 15; data->buff[index]=value; data->size++; printf("%d is located in %d on the buffer\n",value,index ); //consusming // attach data to shared memory index=data->index; value=data->buff[index]; printf("%d now consumed\n",value ); data->size--; data->index++; sem_post(access); sem_post(full); return 0; } 

2 Comments

How do you start the producer and the consumer ? I suggest adding comments about this as a file header. I suggest also you structure the code with 1 routine name producer and 1 routine named consumer. Why do you have 2 shared memory segments ? Are you implementing a well know algorithm ? If yes which one (and it would be nice to have some comments in the code). Otherwise have a look to 2nd algorithm in en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem
@pifor thanks a lot for helps. I've solved it and wrote the consumer and producer processes in different files, and I guess it worked.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.