0

I am trying to create 4 child processes from the main process and in turn the child process will go into critical region lock it and increase the variable counter

when all processes end final counter is printed

in the given code below i am unable to increase the counter

PS: I have read some posts on unnamed semaphores and have seen some posts on stack overflow. either they don't resolve my issue or they are examples of threads and semaphores and not child processes and semaphores

Also i insist on using unnamed semaphore since i am new to this i might be doing some foolish mistake.

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

sem_t mutex;
int counter = 1;


void child(int id){
    // critical region
    sem_wait(&mutex);

    printf("Counter right now for %d is %d\n" , id, counter);
    printf("Increasing counter for %d\n", id);
    (counter)++;
    printf("Counter now for %d is %d\n", id, counter);

    sem_post(&mutex);
}

int main(){
    pid_t pid;
    sem_init(&mutex, 1, 1);

    for(int kid = 1; kid < 5; kid++){
        pid = fork();
        if(pid==0){
            child(kid);
            printf("Counter after child %d is %d\n\n", kid, counter);
            exit(0);
        }
        else{
            printf("parent process %d with counter = %d\n\n", kid, counter);
        }
    }

    int status;
    for(int kid=1; kid<5; kid++){
        wait(&status);
    }

    printf("final counter is %d\n", counter);
    sem_destroy(&mutex);
}

the output i am getting is 1 the output i am expecting is 5

3 Answers3

1

You need to research how fork works and shared memory. Separate processes get separate memory. While copies of some things from the parent are made to the child process, they do not share the same memory.

jwdonahue
  • 6,199
  • 2
  • 21
  • 43
  • so i have to use something like shm or shared memory – Roushan Singh May 08 '20 at 14:51
  • That or a shared file. Semaphores and signal between processes have their limits. One approach might be to use pipes to distribute the updated value to parents, children or siblings. – jwdonahue May 08 '20 at 14:54
  • Note that it's been a very long time since I last worked with any *nix systems, so there might be alternatives I am not aware of. You basically want some kind of inter-process communication (IPC). – jwdonahue May 08 '20 at 14:56
  • you are talking about bidirectional pipes??. I have a program in general which is going to increase or decrease a lot of variables. using pipes seem frustrating. can i put these variables in a struct and use shm. would that be correct or am i missing something – Roushan Singh May 08 '20 at 14:57
  • The pipes can be uni or bi directional depending on your needs. You can transmit entire records over a pipe, but shared memory might be your most efficient method. It really depends on the update rates and whether getting blocked behind that semaphore will become a bottle-neck. They can sometimes lead to serialization of updates, as the process that exits the critical section first, gets it's work done first, and sometimes winds up in the waiting queue before the other processes have completed. That's not always a bad thing, it just depends on what you're designing. – jwdonahue May 08 '20 at 15:03
  • I think shm is what i will go for – Roushan Singh May 08 '20 at 15:11
  • And also see this answer regarding atomics: https://stackoverflow.com/a/11271936/3150445 that would be far more efficient than using a semaphore. At least for the single variable increment case. – jwdonahue May 08 '20 at 15:15
  • would be kind to write an anwer with shared memory and unnamed semaphores. just an example where a struct object with members a and b are updated by 1 1 each. I will figure the rest out – Roushan Singh May 08 '20 at 15:16
  • I don't have a Linux development environment handy to compile and test against, so if someone comes along and wants to answer this question with code, I'll happily withdraw mine. – jwdonahue May 08 '20 at 15:21
  • see the thing is i am new to os programming.and i already appreciate your help. But i get into errors. since i ready your answers and then went to implement shared memeory only to learn later that the semaphore itself should be in the shared space inside a struct. Details like this may have me hanging for hours. thats why i need your answer. – Roushan Singh May 08 '20 at 15:48
  • i know its a lot but would you use this online compiler https://www.onlinegdb.com/online_c_compiler and help me out – Roushan Singh May 08 '20 at 15:50
0

When you create a child process, that child has a copy of all the variables, that means that the memory space they are using are different for each proccess. So when you are doing child(kid); all the childs will enter here and all of them will increase his own variable. You can try to create threads instead of create new processes

Josep
  • 162
  • 1
  • 9
  • Sometimes threads are the wrong way to go, particularly when you want a robust system in the face of failures. A single errant thread can take out an entire processes. – jwdonahue May 08 '20 at 15:06
  • thanks @Josep . I was looking for this kind of warning information. Unfortunately the blogs and articles i referred did not mention this important detail. Would you be willing to show me by what method other than pipes (preferably shared memory stuff) can i be able to accomplish my task – Roushan Singh May 08 '20 at 15:07
  • @jwdonahue You are right, but for the problem Roushan Singh is trying to solve i think threads can be ok – Josep May 08 '20 at 15:09
  • i am learning os concepts and for that reason i wanna do it using unnamed semaphore and shared memory – Roushan Singh May 08 '20 at 15:17
-1

I have written this solution for you, using threads:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
int  counter = 0;
sem_t mutex;

void *increment(void *arg) {
    sem_wait(&mutex);
    int *val;
    val = (int *) arg;
    printf("Counter right now for %d is %d\n" , *val, counter);
    printf("Increasing counter for %d\n", *val);
    counter++;
    printf("Counter now for %d is %d\n", *val, counter);
    sem_post(&mutex);
}
int  main() {
    int i;
    sem_init(&mutex, 0, 1);
    pthread_t  h;
    for (i = 1 ; i < 6 ; i++ ) {
        pthread_create(&h, NULL , increment , &i);
        pthread_join(h, NULL);
    }
    printf ("Final value of counter: %d\n", counter);
}
Josep
  • 162
  • 1
  • 9
  • sorry @Josep. I appreciate your help but i already have the thread based answer. i am looking for process bases IPC and semaphore answer – Roushan Singh May 08 '20 at 16:53