How Do 2 or More Fork System Calls Work

How do 2 or more fork system calls work?

Your program is utterly wrong. You should never ignore the result of fork.

Read the Advanced Linux programming book and the fork(2) man page (read that page several times and carefully).

Typical code should be:

  pid_t pid1 = fork();
if (pid1<0) { perror("fork1 failed"); exit(EXIT_FAILURE); }
else if (pid1 == 0) {
// you are in the child process
}
else // pid1>0
{ // you are in the parent process
}

And likewise for pid_t pid2=fork(); and then for pid_t pid3=fork(); etc....
So each call to fork should handle the 3 cases of result of fork (failure i.e. <0, child process ==0, parent process >0)

In principle you have 33 i.e. 27 possibilities. But you could handle early the failure case, which leaves 23 i.e. 8. possibilities

Don't forget to handle the failure of fork. You might lower your process limit (with setrlimit(2) using RLIMIT_NPROC or the equivalent ulimit bash builtin) to ease the test of fork failure.

Understanding how fork() system call works

This line isn't doing what you think:

if(fork() != -1) { // #1

That will succeed for both the parent and the child (as long as fork is possible, which is almost always the case). You mean to test against 0 here. The parent will get 0, the child will get >0. -1 is an error.

In your case, what you've marked as the "child" legs should never be executed unless there are errors. I don't think that's what you meant. What you're seeing are the initial 2 (parent and child) forks plus 4 (parent+child * 2) second forks. That's 6 forks, which is what the output indicates.

In terms of call-return behaviour, how are the fork() and exec() system calls different from other system calls?

Actually, there are a few which don't obey the "returns once" paradigm.

A call to fork() returns once or twice - the latter on success where it returns once in the parent and once in the child, the former on failure where it simply returns once in the parent.

A call to exec() will return on failure but, if successful, the current process is simply overwritten with a new program.

There are others, such as exit() or abort(), which are not expected to return at all.

Some explanation of the behavior of the fork system call?

You start with process 1.

The first call to fork creates a new process - 2.

Now, 1 and 2 keep running. Both call fork again, you have now created process 3 and 4.

Now you check if the returned pid is 0. If it isn't (which it won't be in process 1 and 2), you call fork again in process 1 and 2 and create process 5 and 6.

Processes 1, 2, 3, 4, 5, and 6 now call printf.

what happens at the lower levels after a fork system call?

It's not so hard right - the kernel half of the fork() syscall can tell the difference between the two processes via the Process Control Block as you mentioned, but you don't even need to do that. So the pseudocode looks like:

int fork()
{
int orig_pid = getpid();

int new_pid = kernel_do_fork(); // Now there's two processes

// Remember, orig_pid is the same in both procs
if (orig_pid == getpid()) {
return new_pid;
}

// Must be the child
return 0;
}

Edit:
The naive version does just as you describe - it creates a new process context, copies all of the associated thread contexts, copies all of the pages and file mappings, and the new process is put into the "ready to run" list.

I think the part you're getting confused on is, that when these processes resume (i.e. when the parent returns from kernel_do_fork, and the child is scheduled for the first time), it starts in the middle of the function (i.e. executing that first 'if'). It's an exact copy - both processes will execute the 2nd half of the function.

How does fork() work?

fork() duplicates the process, so after calling fork there are actually 2 instances of your program running.

How do you know which process is the original (parent) one, and which is the new (child) one?

In the parent process, the PID of the child process (which will be a positive integer) is returned from fork(). That's why the if (pid > 0) { /* PARENT */ } code works. In the child process, fork() just returns 0.

Thus, because of the if (pid > 0) check, the parent process and the child process will produce different output, which you can see here (as provided by @jxh in the comments).

how to create two processes from a single Parent

To create a second process, call fork() again - either within the parent or the child (but not both!). Which you choose depends on whether you want this process to be a child of the original parent or a child of the first child process (it is usual for it to be a child of the original parent).

Communicating through a pipe is much simpler and more reliable than using signals. pipe(), close(), read(), write() and select() are the key functions here.


For example, to have the parent create two child processes, you would do something like:

pid_t child_a, child_b;

child_a = fork();

if (child_a == 0) {
/* Child A code */
} else {
child_b = fork();

if (child_b == 0) {
/* Child B code */
} else {
/* Parent Code */
}
}


Related Topics



Leave a reply



Submit