fork and exec


fork()
The fork() system call creates a new process by duplicating the address space of the calling process.
The new process, called the child process, is an exact copy of the parent process except for a few differences (e.g., unique process ID).
The return value of fork() is:
    In the parent process: The child’s process ID (PID).
    In the child process: 0.
    On failure: -1 (no child process is created).

exec():
The exec() family of functions replaces the current process image with a new one.
It loads the specified program into the current process space and runs it from the entry point.
The most commonly used exec() functions include:
execv: The execv function takes the program name and an array of pointers to null-terminated strings that represent the argument vector, similar to the argv parameter in the main function.
int execv(const char *path, char *const argv[]);

execvp: The execvp function is similar to execv, but it searches for the executable file using the directories listed in the PATH environment variable.
int execvp(const char *file, char *const argv[]);

execve: The execve function is the most flexible, allowing you to specify the environment variables explicitly as an argument.
int execve(const char *path, char *const argv[], char *const envp[]);

execl: The execl function takes the program name and a variable number of string arguments, terminated by a NULL pointer.
int execl(const char *path, const char *arg, ... /* (char *) NULL */);

execle: Similar to execl, but it also allows you to specify the environment variables explicitly.
int execle(const char *path, const char *arg, ..., char *const envp[]);

execvpe: Similar to execvp, but it also allows you to specify the environment variables explicitly.
int execvpe(const char *file, char *const argv[], char *const envp[]);

These functions are typically used to replace the current process image with a new one, loading and executing a new program with the provided arguments. They differ in how they accept arguments, handle environment variables, and search for the executable file.

Using fork() and exec() Together:
Typically, you use fork() to create a child process and then call exec() in the child process to replace its image with a different program.
This allows you to run a different program without affecting the parent process.

Here’s an example in C that demonstrates how to use fork() and execvp() together:

Example:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int main() {
pid_t pid = fork();

if (pid == -1) {

    perror("fork failed");
    exit(EXIT_FAILURE);

} else if (pid == 0) {

// Child process
printf("Child process (PID %d): Executing ls -l\n", getpid());

// Replace the child process with 'ls -l'
char *args[] = {"ls", "-l", NULL};
execvp(args[0], args);

// If execvp fails, print an error
perror("execvp failed");
exit(EXIT_FAILURE);

} else {

// Parent process
printf("Parent process (PID %d): Waiting for child...\n", getpid());
wait(NULL); // Wait for the child process to finish
printf("Parent process: Child process completed.\n");
}

return 0;
}

The following program uses execl.The execl system call has the following syntax

int execl(const char *path, const char *arg0, const char *arg1, ..., const char *argn, (char *) NULL);

Here's what each parameter means:

path: A pointer to a null-terminated string that specifies the path to the executable file. This can be an absolute path (starting from the root directory) or a relative path (relative to the current working directory).

arg0, arg1, ..., argn: These are pointers to null-terminated strings representing the arguments to the new program. arg0 typically represents the name of the program being executed. These arguments are passed to the main() function of the new program.

(char *) NULL: This is a sentinel value, indicating the end of the argument list.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
    pid_t pid = fork(); // Create a new child process

    if (pid == -1) {
        // Fork failed
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // This code is executed by the child process
        // Replace the child process with a new program
        execl("/bin/ls", "ls", "-l", NULL);
        // If execl returns, it means it failed
        perror("execl");
        exit(EXIT_FAILURE);
    } else {
        // This code is executed by the parent process
        // Wait for the child process to finish
        wait(NULL);
        printf("Child process finished.\n");
    }

    return 0;
}

In this example below:

We use the env command to print out environment variables. The env command prints out all environment variables it receives.

We define an array envp containing environment variables. In this case, we set two variables: MY_VARIABLE with the value "Hello World" and PATH with the value "/usr/bin:/bin".

We use execve() to execute the env command with the provided environment variables.

When you run this program, it will print out the environment variables set within the child process, demonstrating how environment variables can be passed to new processes.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    pid_t pid = fork(); // Create a new child process

    if (pid == -1) {
        // Fork failed
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // This code is executed by the child process
        
        // Define the arguments for the new program
        char *args[] = {"/usr/bin/env", NULL};
        
        // Define the environment variables
        char *envp[] = {
            "MY_VARIABLE=Hello World",
            "PATH=/usr/bin:/bin",
            NULL // End of environment variables
        };
        
        // Execute the env command to print environment variables
        if (execve("/usr/bin/env", args, envp) == -1) {
            perror("execve");
            exit(EXIT_FAILURE);
        }
    } else {
        // This code is executed by the parent process
        // Wait for the child process to finish
        wait(NULL);
        printf("Child process finished.\n");
    }

    return 0;
}

Comments

Popular posts from this blog

CSL 204 OPERATING SYSTEM LAB KTU IV SEM CSE

FCFS and SJF

Shared Memory Inter-Process Communication ( IPC)