Amr Mohammed
Amr Mohammed

Reputation: 65

why a shell creates a new process for each command?

I am trying to program a shell in C , and I found that each command is executed in a new process, my question is why do we make a new process to execute the command? can't we just execute the command in the current process?

Upvotes: 0

Views: 1894

Answers (3)

datenwolf
datenwolf

Reputation: 162164

can't we just execute the command in the current process?

Sure we can, but that would then replace the shell program with the program of the command called. But that's probably not something you want in this particular application. There are in fact, many situations in which replacing the process program via execve is a the most straightforward way to implement something. But in the case of a shell, that's likely not what you want.

You should not think processes to be something to be avoided or "feared". As a matter of fact, segregating different things into different processes is the foundation of reliability and security features. Processes are (mostly) isolated from each other, so if a process gets terminated for whatever reason (bug, crash, etc.) this in the first degree affects only that particular process.

Here's something to try out:

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

int segfault_crash()
{
    fprintf(stderr, "I will SIGSEGV...\n");
    fputs(NULL, stderr);
    return 0;
}

int main(int argc, char *argv)
{
    int status = -1;
    pid_t const forked_pid = fork();
    if( -1 == forked_pid ){
        perror("fork: ");
        return 1;
    }
    if( 0 == forked_pid ){
        return segfault_crash();
    }
    waitpid(forked_pid, &status, 0);
    if( WIFSIGNALED(status) ){
        fprintf(stderr, "Child process %lld terminated by signal %d\n",
            (long long)forked_pid,
            (int)WTERMSIG(status) );
    } else {
        fprintf(stderr, "Child process %lld terminated normally\n",
            (long long)forked_pid);
    }
    return 0;
}

This little program forks itself, then calls a function that deliberately performs undefined behavior, that on commonplace systems triggers some kind of memory protection fault (Access Violation on Windows, Segmentation Fault on *nix systems). But because this crash has been isolated into dedicated process, the parent process (and also siblings) are not crashing together with it.

Furthermore processes may drop their privileges, limit themselves to only a subset of system calls, and be moved into namespaces/containers, each of which prevents a bug in the process to damage the rest of the system. This is how modern browsers (for example) implement sandboxing, to improve security.

Upvotes: 1

yoones
yoones

Reputation: 2474

When you execute a command, one of the following happens:

  • You're executing a builtin command
  • You're executing an executable program

An executable program needs many things to work: different memory sections (stack, heap, code, ...), it is executed with a specific set of privileges, and many more things are happening.

If you run this new executable program in your current process, you're going to replace the current program (your shell) with the new one. It works perfectly fine but when the new executable program is done, you cannot go back to your shell since it's not in memory anymore. This is why we create a new process and run the executable program in this new process. The shell waits for this new process to be done, then it collects its exit status and prompts you again for a new command to execute.

Upvotes: 5

Some programmer dude
Some programmer dude

Reputation: 409136

It's because of how the UNIX system was designed, where the exec family of calls replace the current process. Therefore you need to create a new process for the exec call if you want the shell to continue afterward.

Upvotes: 5

Related Questions