Learn exec family of commands

🧠 The exec Family of System Calls in UNIX/Linux


🎯 Purpose

The exec family of functions is used to replace the current process image with a new program.

In simple terms:

exec does not create a new process — it loads a new program into the current process (overwriting it).

So typically:

  1. A parent process calls fork() to create a child.

  2. The child calls an exec function to replace itself with a new program.

This is how most programs (like your shell) launch new applications.


🧩 Analogy

Think of a process as a person reading a book (the program).
fork() makes a clone of the reader (child).
exec() makes the reader throw away the old book and start reading a new one.


⚙️ General Behavior

When an exec function is called:

  • The current code, data, and stack of the calling process are replaced by those of the new program.

  • The process ID (PID) stays the same.

  • Open file descriptors may remain open (depending on flags).

  • Environment variables can be passed to the new program.

If successful, exec never returns — because the old program has been completely replaced.
It returns only on failure (e.g., file not found, permission denied).


🧩 List of Common exec Variants

FunctionDescriptionSearch Path    Argument Type
execl()        Takes a list of arguments    No    List
execlp()        Takes a list, searches PATH    Yes    List
execle()        Takes a list and environment    No    List
execv()        Takes an array (vector) of args    No    Array
execvp()        Takes an array, searches PATH    Yes    Array
execvpe()        Takes an array and environment    Yes    Array

🧩 Syntax

Each variant has a slightly different parameter style.

1️⃣ execl()

int execl(const char *path, const char *arg, ..., (char *)0);
  • path: Full path to the executable.

  • arg: The command-line arguments (arg[0] is the program name).

2️⃣ execv()

int execv(const char *path, char *const argv[]);
  • argv: Array of strings (argv[0], argv[1], …, NULL).

3️⃣ execlp() / execvp()

Same as above but automatically searches for the executable in the directories listed in the PATH environment variable.

4️⃣ execle() / execvpe()

Similar to execl() or execvp(), but with an extra environment array parameter (envp).


🧠 Example 1 – Using execl()

This replaces the current process with /bin/ls.

#include <stdio.h> #include <unistd.h> int main() { printf("Before execl()\n"); execl("/bin/ls", "ls", "-l", (char *)0); printf("This line will not be executed if execl succeeds.\n"); return 0; }

Compile & Run

gcc execl_demo.c -o execl_demo ./execl_demo

Output

Before execl() (total contents of current directory...)

✅ The line after execl() is not printed because the process was replaced by /bin/ls.


🧠 Example 2 – Using execvp() with Arguments

execvp() is the most common version because it:

  • Accepts an array of arguments

  • Searches in the PATH

#include <stdio.h> #include <unistd.h> int main() { char *args[] = {"ls", "-l", "-a", NULL}; printf("Before execvp()\n"); execvp("ls", args); perror("execvp failed"); // executed only if exec fails return 0; }

Output

Before execvp() (total contents of current directory...)

🧠 Example 3 – Using fork() + execvp()

This is the most common use case in Operating Systems labs:

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> int main() { pid_t pid = fork(); if (pid < 0) { perror("fork failed"); exit(1); } else if (pid == 0) { // Child process replaces itself with ls char *args[] = {"ls", "-l", NULL}; execvp("ls", args); perror("execvp failed"); exit(1); } else { // Parent process waits for the child wait(NULL); printf("Child process completed.\n"); } return 0; }

Output

(total directory listing...) Child process completed.

🧠 Example 4 – Using execle() with Custom Environment

#include <stdio.h> #include <unistd.h> int main() { char *envp[] = {"MYVAR=HelloWorld", NULL}; execle("/usr/bin/env", "env", NULL, envp); perror("execle failed"); return 0; }

Output

MYVAR=HelloWorld (other environment variables...)

⚙️ Behavior Summary

PropertyDescription
PID        Same as before exec
Memory        Old program replaced
Open Files        Usually retained unless FD_CLOEXEC set
Signal Handlers        Reset to default
Environment        Passed or replaced
Return Value        Returns -1 on failure only

🧩 Common Usage in Practice

In shells (like bash):

  • The shell forks a new process.

  • The child process calls execvp() to run the user’s command.

  • The parent shell waits for it to finish.

This model (fork()exec()wait()) forms the core of UNIX process management.


🧩 Error Handling

Always handle failures:

if (execvp("somecommand", args) == -1) { perror("exec failed"); exit(1); }

⚙️ When to Use Which

FunctionUse When
execl()You know full path and fixed number of args
execv()You want to pass args as an array
execlp()You want PATH search + list of args
execvp()You want PATH search + array of args (most common)
execle() / execvpe()You want to set custom environment variables

🔍 Verification in Lab

While your program is running, use:

ps -ef | grep <your program> pstree -p

to observe how the child process is replaced with the new executable.


🧾 Summary

Function    Searches PATH    Pass Environment    Args Type
execl()        No        No        List
execv()        No        No        Array
execlp()        Yes        No        List
execvp()        Yes        No        Array
execle()        No        Yes        List
execvpe()        Yes        Yes        Array

🧠 In Short:

  • fork() → creates a new process

  • exec()replaces the current process with another program

  • wait()synchronizes parent and child

  • Together, they form the UNIX process control triad

Comments

Popular posts from this blog

Operating Systems OS Lab PCCSL407 Semester 4 KTU BTech CS 2024 Scheme - Dr Binu V P

FCFS First Come First Serve - CPU Scheduling

Banker’s Algorithm -Finding safe execution sequence