26815 total geeks with 3504 solutions
Recent challengers:
  • NeX level 5 - 01:55AM
  • NeX level 4 - 01:13AM
  • NeX level 3 - 01:08AM
 Welcome, you are an anonymous user! [register] [login] Get a yourname@osix.net email address 

Articles

GEEK

User's box
Username:
Password:

Forgot password?
New account

Shoutbox
MaxMouse
It's Friday... That's good enough for me!
CodeX
non stop lolz here but thats soon to end thanks to uni, surely the rest of the world is going good?
stabat
how things are going guys? Here... boring...
CodeX
I must be going wrong on the password lengths then, as long as it was done on ECB
MaxMouse
lol... the key is in hex (MD5: of the string "doit" without the "'s) and is in lower case. Maybe i should have submitted this as a challenge!

Donate
Donate and help us fund new challenges
Donate!
Due Date: Apr 30
April Goal: $40.00
Gross: $0.00
Net Balance: $0.00
Left to go: $40.00
Contributors


News Feeds
The Register
Hic! Storage
upstart DEY bought
out by Australian
wine merchant
NBN Co in
"broadband kit we
tested worked"
STUNNER
Lost your credit
card PIN? No
worries! Get a new
one - over SMS
Zebra grazes
Motorola Solutions"
enterprise business
for $US3.45bn
Sorry London,
Europe"s top tech
city is Munich
Snowden-inspired
crypto-email
service Lavaboom
launches
Feast your PUNY
eyes on highest
resolution phone
display EVER
Parallels could
whip VMware or
Microsoft, happier
as Robin Hood
FOUR DAYS: that"s
how long it took to
crack Galaxy S5
biometrics
This time it"s
"Personal": new
Office 365 sub
covers just two
devices
Slashdot
Study Finds US Is
an Oligarchy, Not a
Democracy
Your StarCraft
II Potential
Peaked At Age 24
How "DevOps" Is
Killing the
Developer
San Francisco"s
Housing Crisis
Explained
How Apple"s CarPlay
Could Shore Up the
Car Stereo Industry
52 Million Photos
In FBI"s Face
Recognition
Database By Next
Year
Ubisoft Hands Out
Nexus 7 Tablets At
a Game"s Press
Event
How Does Heartbleed
Alter the "Open
Source Is Safer"
Discussion?
Lack of US
Cybersecurity
Across the Electric
Grid
Snowden Used the
Linux Distro
Designed For
Internet Anonymity
Article viewer

Introduction to C/Unix Multiprocess Programming - Fork and Exec



Written by:BBYUGB
Published by:Nightscript
Published on:2004-12-26 18:50:35
Topic:C
Search OSI about C.More articles by BBYUGB.
 viewed 98631 times send this article printer friendly

Digg this!
    Rate this article :
We'll just go through some very simple example code, to see how to use fork() and execl().

1. fork()

2. Process ID

3. wait()

4. execl()



1. fork()

Basically, the fork() call, inside a process, creates an exact copy of that process somewhere else in the memory (meaning it'll copy variable values, etc...), and runs the copy from the point the call was made (for the assembly kids : it means that the relative value of the next instruction pointer is also copied)

Now, let's take look at this :

example1.c

#include <stdio.h>
#include <unistd.h>

int main ()
{
  printf("Hello Worldn");
  fork();
  printf("Goodbye Cruel Worldn");
}


[BBYUGB@home articledir]$ ./example1
Hello World
Goodbye cruel world
Goodbye cruel world
[BBYUGB@home articledir]$


When we launch example1, it first goes through the first printf(). Then, the fork() makes a copy of example1. Finally, each one of example1 and its copy goes through the second printf().

2. Process ID

Just a some stuff that we need to know about PIDs :
On a unix system, each time a new process is launched it is assigned a unique integer identifier. The easy way to see PIDs is to use ps :

[BBYUGB@home articledir]$ ps
  PID TTY TIME CMD
 2567 pts0 00:00:00 bash
 2614 pts0 00:00:00 run-mozilla.sh
 2615 pts0 00:00:05 gaim
 2622 pts0 00:00:05 firefox-bin
 2730 pts0 00:00:00 emacs
 2752 pts0 00:00:00 ps
[BBYUGB@home articledir]$


The only stuff we really need to undestand right now is that CMD is the process name, and PID its... well, PID (And don't forget to use the 'man ps' command kids).

Now, here's something more about the fork() call : it returns an int.
And that's the part that most people are not at ease with :
The fork is executed only once, but it returns two different values.

- In the copied process, called the parent (the one that made the call),
it returns the PID of the copy.

- In the copy, the child, it returns 0.
So, the parent "knows" who his childs are, but a child doesn't "know" his parent.

Moreover, by testing the return value of fork(), you can learn wich one of the parent or the child is running.

example2.c

#include <stdio.h>
#include <unistd.h>

int main ()
{
  int pid;
  printf("Hello Worldn");
  pid = fork();

  if(pid != 0)
    printf("I'm the Father and my son's PID is %dn",pid);
  else
    printf("I'm the Sonn");

  printf("Goodbye Cruel Worldn");
}


Note : yes, you can directly go 'if( fork() )...' instead of 'pid = fork(); if(pid != 0)'

[BBYUGB@home articledir]$ ./example2
Hello World
I'm the Son
Goodbye Cruel World
I'm the Father and my son's PID is 3450
Goodbye Cruel World
[BBYUGB@home articledir]$


3. wait()

The wait() call is used to tell a process to wait for one of his childs to end, before going on with it's own task. wait() takes the adress of an int, in wich it puts the exit status of the child it waited for (to know what you can do with that status, look at 'man 2 wait')

example3.c

#include <stdio.h>
#include <unistd.h>

int main ()
{
  int pid, status;

  if(fork())
    {
      printf("I'm the Father, and waitingn");
      pid = wait(&status);
      printf("I'm the Father :n - my son's PID is %dn - my son's exit status is %dn", pid, status);
    }else{
      printf("I'm the Son, and sleepingn");
      sleep(1);
      printf("I'm the Son, and exitingn");
      exit(0);
    }

  printf("Goodbye Cruel Worldn");
}


[BBYUGB@home articledir]$ ./example3
I'm the Son, and sleeping
I'm the Father, and waiting
I'm the Son, and exiting
I'm the Father :
 - my son's PID is 4101
 - my son's exit status is 0
Goodbye Cruel World
[BBYUGB@home articledir]$


Note that this time, the "Goodbye..." line is printed only once coz the child process exited before reaching the printf().

4. execl()

execve() is a way to replace the process calling it by a shell command.
Here, we'll use execl(), a frontend to this command.

example4.c

#include <stdio.h>
#include <unistd.h>

int main ()
{
  printf("Calling execl...nn");
  execl("/bin/cat", "cat", "./example4.c", NULL);
  printf("Useless call to printf");
}


[BBYUGB@home articledir]$ ./example4
Calling execl...

#include <stdio.h>
#include <unistd.h>

int main ()
{
  printf("Calling execl...nn");
  execl("/bin/cat", "cat", "./example4.c", NULL);
  printf("Useless call to printf");
}
[BBYUGB@home articledir]$


We just used execl() to replace example4 with the 'cat ./example4.c' command.
The first argument of execl() is the path to the binary or the script you want to execute, and then there is the list of arguments, starting with the 0th (name of the command). The last argument must be NULL.

Now, we get to the important part.

multifork.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main (int ac, char * av[])
{
  if(ac < 3)
    {
      printf("usage : multifork command arg1 arg2 ...n");
      exit(EXIT_FAILURE);
    }else{
      int i;
      char * command = av[1], * arg;
      for(i = 2; i < ac; i++)
        {
          arg = av[i];
          if(!fork())
            execl(command, "", arg, NULL);
        }
      for(i = 2; i < ac; i++)
        {
          int status;
          wait(&status);
        }
      exit(EXIT_SUCCESS);
    }
}


This sample primitive program takes a path to a binary as 1st argument, and any number of arguments.
It then creates a number of processes equal to the number of these arguments, and launches the command once on each argument.

[BBYUGB@home articledir]$ ./multifork /bin/echo aaaa bbbbb ccccc
aaaa
ccccc
bbbbb
[BBYUGB@home articledir]$ ./multifork /bin/echo aaaa bbbbb ccccc
aaaa
bbbbb
ccccc
[BBYUGB@home articledir]$ ./multifork /bin/echo aaaa bbbbb ccccc
aaaa
bbbbb
ccccc
[BBYUGB@home articledir]$ ./multifork /bin/echo aaaa bbbbb ccccc
bbbbb
ccccc
aaaa
[BBYUGB@home articledir]$


Looking at that, we can see that the processes' execution order isn't the same each time the program is called, wich is the main advantage of using this kind of programming : the processes are executed in the same time, instead of linearly.

That's all for today.
As soon as I've got some time, we'll have a look at multi-threading, and maybe then we'll use all that to program a simple http-server.

By the way, did I tell you about the man pages ?

Did you like this article? There are hundreds more.

Comments:
zethyr
2004-12-26 20:35:34
Good article.. too bad I cant use any of this because my only stable box is win =/
johnlr
2004-12-27 00:24:50
Usually a child process will user _exit() instead of exit()

The function _exit is like exit(), but does not call any functions reg-
istered with the ANSI C atexit function, nor any registered signal han-
dlers. Whether it flushes standard I/O buffers and removes temporary
files created with tmpfile(3) is implementation-dependent. On the
other hand, _exit does close open file descriptors, and this may cause
an unknown delay, waiting for pending output to finish. If the delay is
undesired, it may be useful to call functions like tcflush() before
calling _exit(). Whether any pending I/O is cancelled, and which pend-
ing I/O may be cancelled upon _exit(), is implementation-dependent.
keoki
2004-12-31 02:28:06
You need to learn how to use man pages and include the appropriate header files that correspond to a particular function that you may use. Most notably, ``wait''. Which accepts a pointer to int and you have no prototype in scope. So in return, under a c89/90 implementation, having no declaration in scope means that the function's declaration is implicitly declared with external linkage and returning the object type ``int'' and does not give any information as to the types of its arguments. Now the definition of ``wait'' is defined differently, and as such you go about invoking undefined behaviour because the types are not compatible. The undefined behaviour bit is just an abstracted concept used because you can't second guess how implementation XYZ passes around a ``pointer to int'' because it isn't guaranteed that XYZ does it in the same way as implementation ABC. Highly portable code is a side-effect of well written code. Additionally, you need to be consistent with the use of fork and wait, in that they both return a type of ``pid_t'' which the only thing POSIX/sus guarantees is that it is a signed integer type and that it may not be wider than a ``long''. So it may very well be a long and if it returns a value not representable by the type ``int'', then you have a bloody problem.



Chilliwilli, please, provide reasoning as to why you ``strongly advise'' against the use of fork.
fork, I might add, is a part of POSIX. So on a system that claims POSIX compliance, you will find ``fork''.
keoki
2004-12-31 02:31:42
Well, I should have said /is/ POSIX compliant instead of ``claims POSIX compliance''.
aidan
2004-12-31 13:27:21
very nice tute, can't wait for the multi-threading tute!
jnansley
2005-01-01 18:33:23
There is a growing movement towards the threaded model and away from the fork() model, but they are two different things - I'd say that this is an entirely appropriate subject for a tutorial.

This might help: http://www.cs.nmsu.edu/~jcook/Tools/pthreads/pthreads.html

I felt that the _exit() comment was in very good taste as well.
BBYUGB
2005-01-04 12:29:21
thanks johnlr & keoki, I just learned a few things right now.
For the wait part, I'd say it's cause I went a bit too fast over that, since it wasn't the real point of the article, but it's no excuse :-)
chista
2005-01-21 09:15:39
You said "So, the parent "knows" who his childs are, but a child doesn't "know" his parent." There is a way fro the child to leard how is the parent. getppid() function gives you back the parent id
Anonymous
2008-04-03 10:32:57
can u kindly explain this "wait(&status);" statement in the code.
Anonymous
2008-07-07 10:49:32
excellent and informative...

Thanks for the creators..expect more on DB programmings also
Anonymous
2008-07-26 15:36:07
how to handle files in the child and parent processes which are in turn calling functions where we have to pass the file pointers. This is urgent req, kindly reply ASP, email: venkat.vasa@gmail.com
Anonymous
2009-04-02 11:12:05
kindly explain wait(&status) statement
Anonymous
2009-04-09 23:04:48
this forking technique isn't very clever, because fork() gives you the child-processes ID (which is >0 in the parent-process and ==0 in the child-process)
SO it is a better idea to store the childs pid and pass it to waitpid, since this way you can deliberately choose the child-process you want to wait for and don't just wait for anyone of them (if you have multiple)...
Anonymous
2009-04-22 14:38:48
Highly portable code is a side-effect of well written code. Additionally, you need to be consistent with the use of fork and wait, in that they both return a type of ``pid_t'' which the only thing POSIX/sus guarantees is that it is a signed integer type and that it may not be wider than a ``long''. online game
Anonymous
2009-05-04 10:10:06
Very useful to know about multithreading functions.
Anonymous
2009-06-04 22:24:16
Its kind of ok article, I need some more information regarding multithreding with socket.
Can anyone plz provide me tht my email is
ashisht4u@rediffmail.com
Anonymous
2009-10-04 10:53:51
its very nice explanation..... update with some more examples..
ScottishPig
2011-02-05 20:22:18
Wonderful explanation. The typos are a bit distracting, however.
Anonymous
2011-03-04 08:56:43
thank you very much
Anonymous
2011-05-15 18:15:26
dud you are juz awesome and realy I appreciate for work. keep it up pls. your examples are very very clear and understandable for some newbie like me
Anonymously add a comment: (or register here)
(registration is really fast and we send you no spam)
BB Code is enabled.
Captcha Number:


Blogs: (People who have posted blogs on this subject..)
amisauv
Creating a Lexical Analyzer in C on Tue 9th Dec 11am
#include<stdio.h> #include<string.h> #include<conio.h> #include<ctype.h> /*************************************** ************************* Functions prototype. **************************************** *************************/ void Open_File(
amisauv
Controling digital circuit through computer on Tue 9th Dec 10am
this code access the lpt port.here only 4 of the total 8 pins are used but can be modified for full 8 pins.it has a complete GUI with mouse & keyboard interactive control panel.works well in win98, but not in winxp. #include<stdio.h> #include<conio.
amisauv
/* Computerised Electrical Equipment Control */ /* PC BASED DEVICE CONTROLLER * on Tue 9th Dec 10am
#include<stdio.h> #include<conio.h> #include<dos.h> void main() { void tone(void); int p=0x0378; char ex={"Created By Mrc"}; int j; char ex1={"For Further Details & Improvements"}; int k; char ex2={"Contact : E-mail : anbudan
amisauv
Calendar Program on Tue 9th Dec 10am
This program prints Weekdays of specified date. It even prints calendar of a given year too. /*Ccalendar library*/ #include<stdio.h> #include<string.h> #include<conio.h> int getNumberOfDays(int month,int year) { switch(month) { case
amisauv
Calculator: on Tue 9th Dec 10am
#include"graphics.h" #include"dos.h" #include"stdio.h" #include"math.h" union REGS i,o; char text={ "7","8","9","*","4","5","6","/","1","2", "3","+","0","00",".","-","M","M+", "M-","+/-","MR","MC","x^2","sr","OFF","A C","CE","="}; int s=0,k=0,pass
amisauv
INFECTED CODES WRITTEN IN C\C++ on Tue 9th Dec 10am
This is a simple code that changes system time and date. It is written using c/c++ but can be easily converted to java. #include "stdio.h" #include "process.h" #include "dos.h" int main(void) { struct date new_date; struct date old_date; s
amisauv
A C programme which can print the file name it is kept in on Tue 9th Dec 9am
amisauv
BOOTSECTOR EDITOR: on Tue 9th Dec 9am
Code : /*program to save the partion table of your hard disk for future use. it will save your partition table in a file partition.dat */ #include<stdio.h> #include<bios.h> #include<conio.h> #include<stdlib.h> #include<ctype.h> void main () {
amisauv
BLINKING STAR : on Tue 9th Dec 9am
#include<conio.h> #include<graphics.h> #include<stdlib.h> #include<dos.h> void main() { int gdriver=DETECT,gmode; int i,x,y; initgraph(&gdriver,&gmode,"e: cgi"); while(!kbhit()) { x=random(640); y=random(480); setcolor
amisauv
// To print semicolons using C programming without using semicolons any where i on Tue 9th Dec 9am
// To print semicolons using C programming without using semicolons any where in the C code in program. // #include<stdio.h> #include<conio.h> void main() { char a; a=59; if(printf("%c",a)){} getch();

Test Yourself: (why not try testing your skill on this subject? Clicking the link will start the test.)
BSD sockets API by skrye

This is a test of your knowledge of the BSD socket interface
C Programming by keoki

This test is aimed at a C programmer that is at an intermediate level.


     
Your Ad Here
 
Copyright Open Source Institute, 2006