Qeustions about Fork()

I have encountered a few problem when using fork()in my assignment. It seems like the output statement of the process is always different with the algorithm that i expected(not following code sequence). May i have more information on how to use fork() and related topics?

Fork, Exec and Process control

Remember that after your program forks, you have two processes: the original parent and the new child. The values of variables set in the parent are NOT copied to the child, which might explain why you’re not getting the result you expect.

In fact, in the classic example, you simply say something like …


// Process ID ...
pid_t pid;

// Create a child process:
pid = fork();

// BOTH processes continue executing at this
// next statement. However, the child process
// will have set "pid" to zero:
if( pid == 0 )
{
   // We're in the child process
}
else
{
   // We're in the parent process
}

Also file descriptors are duplicated in the parent and child. So if both are writing to stdout, you will get mixed output. And if you are using stdio buffering, that has also to be taken into consideration.

Have to see your explanation of what you are doing to comment more.

well,my lecturer didn’t state it clearly…

http://img18.imageshack.us/img18/8656/83411830.jpg

From this diagram,the parent process has 2 children processes.How could it be possible to create 2 children process in a row?(normally we will have 1 parent and 1 child process after the fork())
Is it something wrong with the diagram?

Easy, the parent just calls fork() again.

To let the digram be true it involves two fork() calls. Else the diagram is wrong.

Hmmm … probably be better to let the child call it the second time. Otherwise, you’ll get three children, not two.


// Process ID ...
pid_t pid1, pid2;

// Create two child processes:
pid1 = fork();

// When the child gets here, he'll call fork()
// ... but so will the parent!
pid2 = fork();

// ****************
// Instead ...
// ****************

// Process ID ...
pid_t pid, newpid;

// Create the first child process:
pid = fork();

// (Edited: always initialize variables!)
// (Just to be safe ...)
newpid = (pid_t)1;

if( pid == 0 )
{
   // We're in the 1st child ...
   newpid = fork();

   if( newpid == 0 )
   {
      // We're in child #2
   }
   else
   {
      // We're in child #1
   }
}
else
{
   // We're in the parent process
}


To the original poster: look at “man fork,” “man vfork” and the “see also” suggestions at the bottom of these man pages. Go to that link I posted, which has detailed info on all of these, including Ken’s point about file handles (which has tripped up more than one soul!).

Well no, because that would result in a different inheritance tree:

parent -> child -> grandchild

when what he has to implement is:

parent -> child1
          -> child2

And why would it result in three children? You are probably thinking the child will execute the same code as the parent and create another child. But that’s easy to handle, as you yourself noted, the child knows it’s the child because it begins execution in the branch where the return of the fork is 0. It can then set a variable saying, I’m a child so I won’t fork any further.

More realistically, typically what nearly always happens is that the child process does an exec and overlays itself with a new executable image. This is in fact the basic principle behind shells in Linux/Unix. It’s easy to underestimate the power of this fork/exec model. At the time Unix was invented, in other OSes process creation was something only the kernel could handle so there could only be one command interpreter, the one built into the kernel. It was an epiphany for me to realise that in Unix, the shell is just another user program, and anybody can write and deploy an shell.

Also your phrasing about the values in the parent not being copied to the child is a bit misleading. Yes, there is no copying, but there never was intended to be. What happens is that all the program state of the parent is present in the child at the moment the fork returns and thereafter each process goes its own way. The very first divergence is the value of the return from the fork() call. From that one difference, the two processes can decide what they each will do.

True. I should’ve referred to the diagram provided by the OP’s poster, instead of just thinking how to implement two children. :slight_smile:

And why would it result in three children? … I’m a child so I won’t fork any further.

Another good point.

Also your phrasing about the values in the parent not being copied to the child is a bit misleading …

I linked to that page with a discussion of fork(), vfork(), etc. because it covers all this in great detail. The point I was emphasizing was that, after the child has been created, changes made in the parent won’t be automatically reflected into the child. This has implications.

So: after looking at the diagram again (and now I see why the instructor gave that problem, because it DOES force you to think and understand just how fork() works) …



pid_t pid1, pid2;
int whoami;

pid1 = pid2 = (pid_t)1;

// "whoami" values:
// 0 = parent
// 1 = child 1
// 2 = child 2
whoami = 0;

// Create child 1 ...
pid1 = fork();
if( pid1 == 0 )
{
   // We're in the first child.
   whoami = 1;
}
else
{
   // We're still in the parent, create child 2 ...
   pid2 = fork();
   if( pid2 == 0 )
   {
      // We're in child # 2.
      whoami = 2;
   }
}

// Now you can test "whoami" to see whether you're
// the parent, child 1 or child 2 ... and I leave
// all that to the original poster!

There are plenty of other ways to do it, but that illustrates the principle.

Somehow i did figure it out how to create 2 children in parent process…thanks a lot.