Linux Processes – Process IDs, fork, execv, wait, waitpid C Functions

In this article, we will start from a small explanation of process IDs and then we will quickly jump on to the practical aspects where-in we will discuss some process related C functions like fork(), execv() and wait() .
Linux Processes Series: part 1, part 2, part 3 (this article).

Process IDs

Process IDs are the process identifiers that are non negative numbers associated with a process. These numbers are unique across the processes running in the system.

This uniqueness of the process ID sometimes is used by the process to create some unique filenames. When a process is terminated from system, its process ID is made available for reuse.

But there is a specific delay that is accounted before making the process ID available for reuse. This is because the process ID that was associated with the previous process that is now terminated may well be into use in form of a file name etc. So a delay is added before reusing the same process ID.

Process ID 1 is for the init process. This is the first process that is started once a system boots up.

The program file for the init process can be found either in /etc/init or in /sbin/init. The init process is a user level process but runs with root privileges and is responsible for bringing the system up to a state once the kernel has bootstrapped. The startup files read by the init process to achieve a certain state are

/etc/rc*.d

/etc/init.d

/etc/inittab

Process ID 0 is of the scheduler of the system. It is a kernel level process responsible for all the process scheduling that takes place inside the system.

Process Control Functions

The fork() Function

The resultant new process created by fork() is known as child process while the original process (from which fork() was called) becomes the parent process.

The function fork() is called once (in the parent process) but it returns twice. Once it returns in the parent process while the second time it returns in the child process. Note that the order of execution of the parent and the child may vary depending upon the process scheduling algorithm. So we see that fork function is used in process creation.

The signature of fork() is :

pid_t fork(void);

The exec Family of Functions

Another set of functions that are generally used for creating a process is the exec family of functions. These functions are mainly used where there is a requirement of running an existing binary from withing a process.

For example, suppose we want to run the ‘whoami’ command from within a process, then in these kind of scenarios the exec() function or other members of this family is used. A point worth noting here is that with a call to any of the exec family of functions, the current process image is replaced by a new process image.

A common member of this family is the execv() function. Its signature is :

int execv(const char *path, char *const argv[]);

Note: Please refer to the man-page of exec to have a look at the other members of this family.

The wait() and waitpid() Functions

There are certain situations where when a child process terminates or changes state then the parent process should come to know about the change of the state or termination status of the child process. In that case functions like wait() are used by the parent process where the parent can query the change in state of the child process using these functions.

The signature of wait() is :

pid_t wait(int *status);

For the cases where a parent process has more than one child processes, there is a function waitpid() that can be used by the parent process to query the change state of a particular child.

The signature of waitpid() is :

pid_t waitpid(pid_t pid, int *status, int options);

By default, waitpid() waits only for terminated children, but this behavior is modifiable via the options argument, as described below.

The value of pid can be:

< -1 : Wait for any child process whose process group ID is equal to the absolute value of pid.

-1 : Wait for any child process.

0 : Wait for any child process whose process group ID is equal to that of the calling process.

> 0 : Wait for the child whose process ID is equal to the value of pid.

The value of options is an OR of zero or more of the following constants:

WNOHANG : Return immediately if no child has exited.

WUNTRACED : Also return if a child has stopped. Status for traced children which have stopped is provided even if this option is not specified.

WCONTINUED : Also return if a stopped child has been resumed by delivery of SIGCONT.

For more information on waitpid() check-out the man-page of this function.

An Example Program

Here we have an example where we have made use of all the types of functions described above.

About The Geek Stuff

My name is Ramesh Natarajan. I will be posting instruction guides, how-to, troubleshooting tips and tricks on Linux, database, hardware, security and web. My focus is to write articles that will either teach you or help you resolve a problem. Read more about Ramesh Natarajan and the blog.