Using the Clone() System Call

Linux has introduced a new call, clone(), which allows a new level of process context creation.

Low-level C programming has always been seen as the arena of the "guru". In my upper level operating systems course, the professor thought this was an idea that should be wiped from our minds. To this end, we had quite a few programming assignments that pushed us into totally new territories. One of these assignments was to research and use the clone() system call provided by Linux. Finding information on the low-level system calls provided by Linux was no easy task. Hopefully, this article will save any other budding guru-wannabees some time and trouble.

C programmers in the UNIX world have long used the fork() system call. This call is the basis of multiprocessing, as this is how new processes are created. Actually, for most systems, this is the only way to create a new process. Linux has introduced a new call, clone(), which allows a new level of process context creation.

Processes come in two basic flavours, heavy-weight and light-weight. Heavy-weight processes are those that you normally think of when you run a program. They contain their own address space and program execution context (see Figure 1). Light-weight processes are normally thought of as threads. These light-weight processes share the address space of the parent, and only contain some subset of the context elements (see Figure 2).

Before looking at the clone() system call, I'll begin with a quick review of fork. This system call, along with the class of exec system calls (i.e., execl(), execlp(), execv(), execvp()) is actually the way your shell executes programs given on the command line. A simple example of using fork() is given in Listing 1. The parent opens a file, assigns a value to a variable and forks a child. The child then tries to change the variable and close the file. After exiting, the parent wakes up and checks to see what the variable is and whether the file is open.

Listing 1

As you can see, the child is in a totally new address space. Within this address space, the child process receives a copy of everything the parent had at the point of forking. (This isn't exactly true in Linux. The child only receives a new copy of a memory page when it tries to make a change to something in that page. Until then, it simply uses the parent's copy. This is called copy-on-write memory management.) Changes to this copy do not affect the parent. When the child tries to change the value of the variable, the parent doesn't see this change.

Listing 2

How would you write a similar program using the clone() system call? Listing 2 gives a very basic program that looks like it copies the behaviour of the program using fork(). The most obvious difference at this stage is the fact that the clone() system call leaves all memory management up to the programmer. The first thing to be done is allocating space for the stack of the new child thread with malloc(). Once this is done, the clone() call is issued to begin a new context of execution, starting at the beginning of the given function. The general signature of this system call is

int __clone(int (*fn) (void *arg), void *child_stack, int flags, void *args)

As you can see, there are several parameters to prepare. The first parameter is a pointer to a function which returns an integer. In C, function names are pointers to functions, so this is easily taken care of. The second parameter is a pointer to the stack space that was set up for the child. You will have to decide how much space is required for the operations the child process will perform. The last parameter is a pointer to the arguments that will pass to the function that the child process will execute. In this case, that is a null pointer, since we aren't passing any arguments to the function.

The third parameter deserves special attention. This is where you can designate the flags which will define how much of the process context will be shared between the child and the parent. As in most C functions, multiple flags are simply read together. The flags available to the clone call are:

CLONE_VM - share memoryCLONE_FILES - share file descriptorsCLONE_SIGHAND - share signal handlersCLONE_VFORK - allow child to signal parent on exitCLONE_PID - share PID (not implemented yet)CLONE_FS - share filesystem

You can see that we've set up our sample program with CLONE_VM and CLONE_FILES. Looking at the output of the program, you can see that the child process will share the address space and file descriptor table with its parent. Any changes made by one process are now visible to the other. If the exact behaviour of fork() was required, all that needs to be changed is which flags are set. This way, you get to choose the exact level of sharing your program will use.

There are a few caveats I should mention in using this system call. Several functions, such as printf(), which are not thread-safe when used with clone(). These functions assume the kind of wrapping that occurs when using thread libraries, like linuxthreads. If you are experimenting with a program and run into segfaults or coredumps, this would be a likely place to look to start your troubleshooting. A possible solution would be to use lower level system calls, such as write() instead of printf(). Also, you should compile programs using the -static switch.

I am in debt to the good folks at Red Hat for pointing out some pitfalls while I stumbled my way through this article. Any errors in this article are entirely the fault of the author, and I would appreciate any corrections that you think should be made.

______________________

Joey Bernard has a background in both physics and computer science. This serves him well in his day job as a computational research consultant at the University of New Brunswick. He also teaches computational physics and parallel programming.

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

nice article

saurabh_verma's picture

Good read .

I think when we use clone()

Jayashree K J's picture

I think when we use clone() , it is a wrapper in C-library. Then after calling this wrapper , it in turn calls the actual clone(2) system call. If this is true then you have to mention it properly.
Looking for ur future & early updations, I remain.

Jayashree K J.
Bangalore ( NTPL ).
31st May, 2006.

How can Joey Bernard will be

Anonymous's picture

How can Joey Bernard will be able to become a fully ordained priest of the Church of Tux, because his current profession is as a computer scientist ???????

How can Joey Bernard will be

Anonymous's picture

How can Joey Bernard will be able to become a fully ordained priest of the Church of Tux, because his current profession is as a computer scientist ???????

Re: Using the Clone() System Call

Anonymous's picture

WOW! i have been looking for manual for clone for weeeks!!! its been driving me up the wall!!!!!!!!!!!!!!!!!!! thankyou so much!!!

Leon

great article.

sathish's picture

truely a good article.

Herr Fähnders, hier ist doch

IN-B3's picture

Herr Fähnders, hier ist doch alles auf Englisch! :(((((

Hier ist die Uebersetzung:

Translator's picture

Hier ist die Uebersetzung:

http://babelfish.altavista.com/babelfish/trurl_pagecontent?url=http%3A%2...

Viel Spass beim Lesen

Re: Using the Clone() System Call

joeybernard's picture

I've come back from the proverbial grave. While googling myself, I came across this verrry old article I had written. With more experience under my belt, I realize I was very stupid in parts of this article. I will be posting a link to an updated version here in the next few weeks if anyone who finds this article wants a corrected version.

Re: Using the Clone() System Call

Anonymous's picture

Please do post an updated version. I found this article very helpful.

Re: Using the Clone() System Call

Anonymous's picture

Hi
Kindly send me updated link
Please do the necessary changes u r mentioning

also can u mention some link i could use for clone()

I am a university student
Thanks
Vipul

u03138@cs.unipune.ernet.in

Re: Using the Clone() System Call

Anonymous's picture

I was wondering why in the source code (listing 2) do you use a void **, when void * could very well be used for the child stack pointer

Rohit

Hey, the stack grows downwards!

Anonymous's picture

Hi,

I'm Pablo, a humble reader from Argentina.

I found your article very interesting, however I couldn't run the code from figure 2. I did compiled it, but the execution of the clone call, lead to a segmentation fault.

I took a look at the clone's man page and it said that the you should pass a pointer to the stack pointer of the task, not the beginning of the stack.

So, as the stack decreases, and it's empty when the thread begins, the right address would not be child_stack, but child_stack + 65383.

Only that way the code runs fine.

Hope it helps.

Regarding child_stack of clone

vijay's picture

How you are calculating as 65383.
How much should we need to allocate for malloc.
how to calculate malloc size.

Re: Hey, the stack grows downwards!

Anonymous's picture

Well, it worked for me. I overlooked the -static option to cc the first time and got a segmentation fault.

Re: Hey, the stack grows downwards!

Anonymous's picture

Using:

child_stack + 65383

still segments for me. Where does 65383
come in? 4 * 16384 -> 65536 anyhow!

child_stack + 4000

works for me i.e. address is a definitely safe
one to use.

David (djjohn@essex.ac.uk)

Re: Hey, the stack grows downwards!

Anonymous's picture

You should write instead:

#define CHILD_STACK_SIZE 16384

clone( child_process, child_stack + CHILD_STACK_SIZE / sizeof( void ** ), CLONE_VM | CLONE_FILES, NULL );

Which is equivalent to CHILD_STACK_SIZE / 4 on most systems.

Re: Hey, the stack grows downwards!

Anonymous's picture

Hi I am manjeet,

even I faced the same problem (of segmentation fault) but

couldnt get out of it even after changing the child_stack pointer ...

Re: Using the Clone() System Call

Chupacabra's picture

I am Chupacabra! Fear my use of the Clone() System Call!

CNN.com

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix