15 January 2009

CoW - Linux way of creating process

Linux operating system is one of THE most popular operating systems and continue to lead the embedded operating systems markets. In this blog, I would like to give an overview of a design decision in Linux and it is one of the reasons why I see Linux not only as Software but also as an Art. The kernel developers thought leadership is unquestionable. I am great fan of Linux Kernel Developers. Without bogging you down, let me come to the point directly. The rest of this post tells one of the reasons "why Linux is masterpiece?".

UNIX operating systems create processes using the system call fork () and overlay (load) a binary/executable image using exec () system call. The system call fork () does not have a parameter and the system call exec () few parameters to load a program from a permanent storage (File System). Practically, the system calls fork () and exec () are twins; fork () is the elder brother and exec () is the younger one. Let us first see the functionality of “fork”. As you may know a process is program in execution that has a state such as data, heap, stack, pending signals, open files and environment variables. When you want to execute something, let us say running a command “ls” from the shell, the “shell” process typically calls fork (). When the fork () is successful, the kernel creates another process which is copy of the process. So each successful call to fork () returns twice – once in the called process (aka parent process) and second time in the newly created process (aka child process). As a standard, all the operating systems copy the address space of parent process and create another address space. There is a overhead involved while creating fork’ ing a process.

Shortly after the process is created, either parent or child process is loaded with some other program. Typically, one of the system calls in “exec” family of system calls is used. When “exec” is executed, the entire address space of the called process is recreated. So there is considerable amount time spent in this “double creation”. Surely, there is some kind of optimization can be done to gain substantial performance.

In Linux, fork () does not copy the address space but just simply creates the kernel data structures needed to the new process. Now, both the parent and child process uses the same address space and the entire address space is marked read-only. So, both the parent and child process can continue to read the process address. When any one process tries to write to a page (memory page), the kernel duplicates the address space and creates the address space. But this is unlikely to occur. Another scenario is the loading a new program into memory. When this occurs, the kernel any way creates a fresh address space and starts to execute the loaded program. By this approach, the “double creation” is avoided. The deferring the duplication of address space has given a performance and sometimes procrastination helps.

The functionality of fork () is called CoW – Copy on Write. So from next time, when you see a Linux box and a running process think about CoW. But you have two process after fork (), which process will be scheduled first? Yes, Linux is a masterpiece. On a lighter note, CoW can also be described pictorially as below.

Taken from from my previous blog


phred said...

I like your "software as art" approach. Few people seem to appreciate the beauty of good design in something as huge and complicated as an OS kernel. Just wanted to note, too, that much of the beauty here is due to the design of the Unix fork() system call,

Lakshmi Narayanan N said...


Thanks for your comments.

Undoubtedly, I 200% agree with you about Unix elegance and simplicity. Not only fork(), Unix taught this world how clearly manage devices and yet provide services to user space via system call.