I wrote this tutorial as part of my work on
AGROS, the Unix shell (as usual, everyone is invited to join). A couple of things you should note:
* This will not work on Windows, as it deals with processes differently.
* This will only work on Unix. When I say Unix I mean any POSIX compliant operating system and of course that includes Linux. Can anyone confirm that it does work on a Mac?
What are processes?
A process (sometimes referred to as a job) is an instance of a program getting executed by the processor. For instance when I type 'ls -al' in a terminal, I'm starting a new process. To simplify, processes are generally characterized by a process ID (or PID), a parent process (more on that in the next section) and a command line.
How to create a new process?
As we have seen before, every process has a parent. To be more precise, I would say that the only way to create a process on a Linux system is to fork it from an existing one. In C, the
unistd.h has a function that does exactly that. This function is (unsurprisingly) called
fork(). Let's take a closer look.
Here's the function header:
pid_t fork(void);
As you can see, its use seems fairly simple. You call the function and it creates a new process. We'll look into the return value of pid_t later. Now it is important to mention that the child process is exactly similar to the parent process. Try executing this code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main (int argc, char** argv){
fork();
fprintf (stdout, "Hello World! My current PID is: %d\n", getpid());
return EXIT_SUCCESS;
}
Result:
Hello World! My current PID is: 19858
Hello World! My current PID is: 19859
Once fork is called, a new process is spawned. The getpid() function returns the current PID of the function, and as you can see, the fprintf function has been executed twice: Once by the parent process and one by the child. (The order of execution can be managed with specific functions like wait() or sleep())
The problem is that both processes behave the exact same way, executing the same lines of code. In 99% of the cases, that's not what you will want your child process to do. In order to distinguish between the two processes, we will use the return code of the fork() function.
Return code?
Now this is the tricky part: fork() will not return the same value in both processes. Try this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main (int argc, char** argv){
int var;
var = fork();
fprintf (stdout, "Hello World! My current PID is: %d; The value of var is:%d\n", getpid(), var);
return EXIT_SUCCESS;
}
Result:
Hello World! My current PID is: 20019; The value of var is: 20020
Hello World! My current PID is: 20020; The value of var is: 0
Let's take a closer look. We have stored the return value of fork() in the var variable. The first line is the output of the parent process. In this line, var has the value of the PID of the child (spawned) process. In the second line, the child process, var has the value 0. This will always be true. As a general rule, fork returns:
* The PID of the child in the parent process.
* 0 in the child process.
And now we can easily separate them. Look at this following code.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main (int argc, char** argv){
int var;
var = fork();
if (var == 0)
fprintf (stdout, "I am the child process! My current PID is: %d\n", getpid());
else
fprintf (stdout, "I am the parent process! My current PID is: %d\n", getpid());
return EXIT_SUCCESS;
}
Result
I'm the parent process! My current PID is: 20160
I'm the child process! My current PID is: 20161
There you go. Hope that was helpful :-)