Using the Clone() System Call
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.
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.
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.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?
| Designing Electronics with Linux | May 22, 2013 |
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
- New Products
- Linux Systems Administrator
- Senior Perl Developer
- Technical Support Rep
- UX Designer
- Web & UI Developer (JavaScript & j Query)
- Designing Electronics with Linux
- Dynamic DNS—an Object Lesson in Problem Solving
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- Reply to comment | Linux Journal
3 hours 34 min ago - Reply to comment | Linux Journal
3 hours 50 min ago - Favorite (and easily brute-forced) pw's
5 hours 41 min ago - Have you tried Boxen? It's a
11 hours 33 min ago - seo services in india
16 hours 4 min ago - For KDE install kio-mtp
16 hours 5 min ago - Evernote is much more...
18 hours 5 min ago - Reply to comment | Linux Journal
1 day 2 hours ago - Dynamic DNS
1 day 3 hours ago - Reply to comment | Linux Journal
1 day 4 hours ago



Comments
nice article
Good read .
I think when we use clone()
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
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
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
WOW! i have been looking for manual for clone for weeeks!!! its been driving me up the wall!!!!!!!!!!!!!!!!!!! thankyou so much!!!
Leon
great article.
truely a good article.
Herr Fähnders, hier ist doch
Herr Fähnders, hier ist doch alles auf Englisch! :(((((
Hier ist die Uebersetzung:
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
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
Please do post an updated version. I found this article very helpful.
Re: Using the Clone() System Call
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
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!
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
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!
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!
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!
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!
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
I am Chupacabra! Fear my use of the Clone() System Call!
CNN.com