1

This is my problem:

  • Create processes
  • Make a shared variable of char buffer
  • Each process will write a char value (for lets say 50 times) i.e. 'A','B', 'C' etc. into the shared memory and will print out the buffer size after it ends
  • I need to add sleep statement so that the order of adding char values to shared value is like this Child -> Grand child 1 -> Grand child 2 -> Great Grand child 1 -> Great Grand child 2
  • At the end print the final buffer

So first of all I want to create process like this, parent process will have a child process. Child process will have grand child process each and each one of the grand child will have great grand child as show here.

enter image description here

I am using IF-ELSE structure to achieve this but I need to create all process first and then start working, don't know how to achieve this. I don't know what is wrong with the code processes are not adding anything into the buffer or the shared value. The reason I am saying this because when process print the buffer size after its execution, it is same for each process.

Code

#include <iostream> 
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include<stdio.h> 
#include <sys/wait.h>
#include<sys/ipc.h>
#include<sys/shm.h>
using namespace std; 
  
// Driver Code 
int main() 
{     
    // number of chars values the process will write
    int child_chrs = 1000;
    int grand_child1_chrs = 700;
    int grand_child2_chrs = 300;
    int great_grand_child1_chrs = 700;
    int great_grand_child2_chrs = 300;
    int fd[2];
    pipe(fd);
    int shared_index = 0, n =0;
    write(fd[1], &n, sizeof(n));
    key_t key = ftok("shmfile",65); // generate unique key 
    int shmid = shmget(key,1024,0666|IPC_CREAT); // get identifier in shmid
    char *stringValue = (char*) shmat(shmid,(void*)0,0); // attach to shared memory
    cout << "Parent process has been created." << endl;
    cout << "Shared memory creation was successful." << endl;
    
    if (fork() == 0) // Child
    {
        if(fork() == 0) // Grand Child 1
        {
            if(fork() == 0) // Great Grand Child 1
            {
                while(great_grand_child1_chrs!=0)
                {    
                    shared_index = read(fd[0], &shared_index, sizeof(int));
                    *(stringValue+shared_index) = 'Y';
                    great_grand_child1_chrs--;
                    shared_index++;
                    write(fd[1], &shared_index, sizeof(int));
                    
                }
                cout << "From Great-grandchild1 process - I just finished and the buffer size = " << shared_index << endl;
                cout << "From Great-grandchild1 process terminated normally\n";
            }
            else // Great Grand Child 2
            {
                while(grand_child1_chrs!=0)
                {
                    shared_index = read(fd[0], &shared_index, sizeof(int));
                    *(stringValue+shared_index) = 'B';
                    grand_child1_chrs--;
                    shared_index++;
                    write(fd[1], &shared_index, sizeof(int));
                    
                }
                cout << "From Great-grandchild2 process - I just finished and the buffer size = " << shared_index << endl;
                cout << "From Great-grandchild2 process terminated normally\n";
            }
        }
        else // Grand Child 2
        {
            if(fork() == 0) // Grand Child 1
            {
                if(fork() == 0) // Grand Child 2
                {
                    while(great_grand_child2_chrs!=0)
                    {
                        shared_index = read(fd[0], &shared_index, sizeof(int));
                        *(stringValue+shared_index) = 'Z';
                        great_grand_child2_chrs--;
                        shared_index++;
                        write(fd[1], &shared_index, sizeof(int));
                        
                        //cout<<"\nshared index: "<<shared_index;
                    }
                    cout << "From Grandchild1 process - I just finished and the buffer size = " << shared_index << endl;
                    cout << "The Grandchild1 process terminated normally.\n";
                }
                else // Grand Child 2
                {
                    while(grand_child2_chrs!=0)
                    {
                        shared_index = read(fd[0], &shared_index, sizeof(int));
                        *(stringValue+shared_index) = 'C';
                        grand_child2_chrs--;
                        shared_index++;
                        write(fd[1], &shared_index, sizeof(int));
                        
                    }
                    cout << "From Grandchild2 process - I just finished and the buffer size = " << shared_index << endl;
                    cout << "The Grandchild2 process terminated normally.\n";
                }
            }
            else // Child
            {
                while(child_chrs!=0)
                {
                    shared_index = read(fd[0], &shared_index, sizeof(int));
                    *(stringValue+shared_index) = 'A';
                    child_chrs--;
                    shared_index++;
                    write(fd[1], &shared_index, sizeof(int));
                    
                }
                cout << "From Child process - I just finished and the buffer size = " << shared_index << endl;
                cout << "The Child process terminated normally.\n";
            }
        }
    }
    else // Parent
    {
        wait(NULL);
        cout<<"\n\nResultant Buffer is:\n\n";
        cout << "From Parent process - I am exiting and final buffer size = " << shared_index << endl;
        shmdt(stringValue);
        cout << "Shared memory has been released.\n";
    }
}

Output

From Child process - I just finished and the buffer size = 5                                                                  
The Child process terminated normally.                                                                                        
                                                                                                                              
                                                                                                                              
Resultant Buffer is:                                                                                                          
                                                                                                                              
From Parent process - I am exiting and final buffer size = 0                                                                  
Shared memory has been released.                                                                                              
From Grandchild2 process - I just finished and the buffer size = 5                                                            
The Grandchild2 process terminated normally.

Note: I know the code is in C++ and it needs to be in C the example that I found was in C++ when I started coding this, but I don't the changes that will make it a C code. I might be doing silly mistakes as I am not a great C programmer I am experienced in Java, Python, Ruby and C# but C is not something I have experience in.

tadman
  • 208,517
  • 23
  • 234
  • 262
Zain Arshad
  • 1,885
  • 1
  • 11
  • 26
  • Is this "Can you convert this C++ code to C?" – tadman Oct 05 '20 at 04:17
  • No I am not asking to convert I will do it myself, but as my code is not working as expected I need to fix it first – Zain Arshad Oct 05 '20 at 04:25
  • `shared_index = read(fd[0], &shared_index, sizeof(int));` seems wrong. That will overwrite the data you read from the pipe with the return code of `read` (which will be either `sizeof(int)`, `0` or `-1`). – Some programmer dude Oct 05 '20 at 04:30
  • 1
    Also note that for any pointer or array `p` and index `i`, the expression `*(p + i)` is *exactly* equal to `p[i]`. The latter syntax is easier to read and write. So please don't write e.g. `*(stringValue+shared_index)`, but instead `stringValue[shared_index]`. – Some programmer dude Oct 05 '20 at 04:32
  • Side note: the family tree is a poor analogy for inheritance. A derived class [is-a](https://en.wikipedia.org/wiki/Is-a) base class. So in the family tree, the child is a parent, and a grandparent and this makes no sense. See [What is an example of the Liskov Substitution Principle?](https://stackoverflow.com/questions/56860/what-is-an-example-of-the-liskov-substitution-principle) for a handy tool to help understand when an inheritance hierarch makes sense – user4581301 Oct 05 '20 at 05:12

1 Answers1

3

Please visit https://www.man7.org/linux/man-pages/man2/read.2.html to understand the syntax of read() system call.

On success, it returns the number of bytes it read which is 4 here.

For example,

shared_index = read(fd[0], &shared_index, sizeof(int));

Will always return 4 as the number of bytes it read successfully.

So please change your logic there.