user1060517
user1060517

Reputation: 375

Global values modified by child process are not accessible to the parent process in main loop

In the main(), I call a function create_child() which forks a child process and then executes a command which runs in the background. I use getpid() to get the pid of the child in a global variable, which is accessed by the parent in the main loop. However, i dont see the child pid value in the main loop. following is the pseudocode-

pid_t pids[2];

create_child(cmd,counter) {

 i=fork();
 if(i<0) exit(1);
 if(i==0) { 
   pids[counter]=getpid();
   ret=system(cmd);
   //when system returns exit 0;
  }
 }


 main() {
   counter=0;
   create_child(cmd,counter);
   if (pids[counter]==xxx) {

     -----
    }
 }

Upvotes: 1

Views: 1867

Answers (3)

Whoami
Whoami

Reputation: 14408

1) Once the parent forks a new process, new process has a life and there by it has its own data. New process inherits the data from the parent, and Child's own copy is created while child tries to modify the data. This concent is called CopyOnRight. That is why the changes being made by child is not seen by parent. Even if you create a Heap Data element [Ie: Dynamic memory allocation ], the same concept is applicable. Let's take the following example.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main (int arg, char ** argv )
{
    pid_t pid;
    int *p = malloc (sizeof(int));
    printf ("\n Globally Assigned 99 to *p\n ");
    *p= 99;

    pid = fork ();
    if (pid > 0)
    {
            printf ("\n Parent Changed *p to 100 \n ");
            *p=100;
            wait (NULL);
            printf (" Prent Exiting..\n");

    } else {
            sleep(10); /* I want to give preference to my parent :) */
            printf ("..Child fetching the value  *p is %d \n", *p);
    }

}

2). As explained by @Mathieu, pipe is also can be used to communite between two processes. Let's look at the folloing sample code which uses shared memory between parent and child. Compare this with the program given in (1). See!!! I have not done any error checking as my intention is project the concept!!!.

#include <sys/mman.h>
#include <sys/stat.h>        
#include <fcntl.h>           
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


int main ( int arg, char ** argv )
{
        int sId;
        int * ptr= NULL;
        pid_t pid;

        /* We create a shared memory object */
        sId = shm_open("MySharedData", O_RDWR|O_CREAT|O_TRUNC, 0666);

        /* We allocate memory to shared object */         
        ftruncate (sId, 512);

        /* we attach the allocated object to our process */
        ptr = (int *) mmap (NULL, 512, PROT_READ|PROT_WRITE, MAP_SHARED, sId, 0);
        printf ("\n Globally Assigned 99 to *p\n ");
        *ptr=99;
        pid = fork ();
        if (pid > 0)
        {
                printf ("\n Parent Changed *p to 100 \n ");
                *ptr=100;
                wait (NULL);
                printf (" Wow Child canged to %d \n", *ptr);
                printf (" Prent Exiting..\n");

        } else {
                sleep(10); /* I want to give preference to my parent :) */
                printf ("..Child fetching the value  *p is %d \n", *ptr);
                *ptr=1234;
        }
}

In program (2), you can see the changes in the parent that's been modified by the child and vice versa, as the shared memory is shared memory is common to both parent/child, rather than having both seperate memory location.

Hope this helps!!!.

Upvotes: 0

Mathieu_Du
Mathieu_Du

Reputation: 827

You'll need a pipe to get back the pid. when you fork, the child inherits a copy of the current variables of the process. If you want to store any changes made by the child, you'll have to pipe them to the parent: pseudocode:

int fd[2];
int id;
pipe(fd);
id = fork();
if (id == 0)
{
    close (fd[0]);
    pid = getpid();
    write (fd[1], pid, nbytes)
    exit(0);
}
else
{
    close(fd[1]);
    read(fd[0], buffer, nbytes);
}

You're then free to use the buffer to modify your global variable.

Upvotes: 0

AusCBloke
AusCBloke

Reputation: 18492

I use getpid() to get the pid of the child in a global variable, which is accessed by the parent in the main loop.

When you execute a fork, a copy of the parent's address space is made for the child. Therefore the child will have a copy of the parent's variables, however modifying any variables in the parent or child will not see the changes also being made to the other one.

From the manpages for fork:

On success, the PID of the child process is returned in the parent, and 0 is returned in the child.

If you want to record the PID of the child in the parent, then have the parent store the return value of fork. If the return of fork is not 0, then you're in the parent. From here, have the parent store the PID. ie:

pid_t ret = fork();

if (ret < 0) { /* failed */ }
else if (ret == 0) { /* child, do exec */ }
else { /* parent, store PID */ }

Upvotes: 1

Related Questions