1
The fork() system call
System-calls
Fork
Process
Parent-child
Linux

In Unix-like systems to create a new process fork() system call is used. The process that calls fork() is the parent process and the newly created process is its child.

int main()
{
    int a=50;
    pid_t process;
    process= fork();
    if(process==0)
    printf("Hi! I am a Child process\n");
    else
    printf("Namaskar _/\_ , I am a Parent process\n");
}

What happens after the fork() system call is interesting as now there are two processes and they must have separate address space. But in Linux a technique called copy-on-write is used, due to this the parent and child share a single copy of the process address space.

If any attempt to write into the process address space is made by any of the two processes then a separate copy is created for that process and now no longer they share the same address space. This technique is used mostly because it prevents the wastage of copying large amount of data as many times the exec() system call is used by the child process to create an altogether different process.

In Linux what fork() does is that it implements the clone() system call, this call takes a series of flags that determine which resources, if any, must be shared between the parent and the child. The clone() system call in turn calls the do_fork().

The do_fork() is defined in kernel/fork.c, line 1566 as of kernel 3.13. The do_fork() does the work of process creation in a synchronized state. The do_fork() now calls copy_process() function.

In the copy_process function all the main work takes place, may vary depending on the architecture, but in general it does the following:

  • It calls dup_task_struct(), which creates a new kernel stack, thread_info structure, and task_struct for the new process. The new values are identical to those of the current task also the child and parent process descriptors are identical at this point.

  • Process descriptor are cleared or set to initial values. Members of the process descriptor that are not inherited are primarily statistically information. The bulk of the data in the process descriptor is shared.

  • Next, the child's state is set to TASK_UNINTERRUPTIBLE, to ensure that it does not yet run.

  • Now copy_flags() is called to update the flags member of the task_struct.

  • Next, pid is assigned.

  • Depending on the flags passed to clone() what resources are to be shared is decided.

  • The remaining time slice is split between the parent and the child.

  • Finally the copy_process() returns to the the caller a pointer to the newly created child process.

Coming back to do_fork() if copy_process() returns successfully then the new child is woken up and run. The do_fork() returns the child process id.

Coming back to the code, the parent and child both processes start executing from the line following the fork() function.

Output
Namaskar _/\_ , I am a Parent process
Hi! I am a Child process
Author

Notifications

?