0% found this document useful (0 votes)
69 views

Artigo PDF

This document provides an introduction to C/Unix multiprocess programming using fork() and execl(). It includes examples of how fork() duplicates a process, how the return value indicates the parent and child processes, how wait() pauses a parent process until a child exits, and how execl() replaces the current process with another program. It concludes with a multifork program that uses these techniques to run a command concurrently on multiple arguments.

Uploaded by

dongutsi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
69 views

Artigo PDF

This document provides an introduction to C/Unix multiprocess programming using fork() and execl(). It includes examples of how fork() duplicates a process, how the return value indicates the parent and child processes, how wait() pauses a parent process until a child exits, and how execl() replaces the current process with another program. It concludes with a multifork program that uses these techniques to run a command concurrently on multiple arguments.

Uploaded by

dongutsi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

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
We'll just go through some very simple example code, to see how to use [b]fork()[/b] and [b]execl()
[/b].
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 fromthe 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'mthe Father and my son's PID is %dn",pid);
else
printf("I'mthe 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'mthe Son
Goodbye Cruel World
I'mthe 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'mthe Father, and waitingn");
pid =wait(&status);
printf("I'mthe Father :n - my son's PID is %dn - my son's exit status is %dn", pid, status);
}else{
printf("I'mthe Son, and sleepingn");
sleep(1);
printf("I'mthe Son, and exitingn");
exit(0);
}
printf("Goodbye Cruel Worldn");
}
[BBYUGB@home articledir]$ ./example3
I'mthe Son, and sleeping
I'mthe Father, and waiting
I'mthe Son, and exiting
I'mthe 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 programtakes 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 programis
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
programa simple http-server.
By the way, did I tell you about the man pages ?
This is an article fromhttp://www.osix.net - view the original at: http://www.osix.net/modules/article/?
id=641

You might also like