Bash knows nothing about ELF. It simply sees that you asked it to run an external program, so it passes the name you gave it as-is to execve(2)
. Knowledge of things like executable file formats, shebang lines, and execute permissions lives behind that syscall, in the kernel.
(It is the same for other shells, though they may choose to use another function in the exec(3)
family instead.)
In Bash 4.3, this happens on line 5195 of execute_cmd.c
in the shell_execve()
function.
If you want to understand Linux at the source code level, I recommend downloading a copy of Research Unix V6 or V7, and going through that rather than all the complexity that is in the modern Linux systems. The Lions Book is a good guide to the code.
V7 is where the Bourne shell made its debut. Its entire C source code is just a bit over half the size of just that one C file in Bash. The Thompson shell in V6 is nearly half the size of the original Bourne shell. Yet, both of these simpler shells do the same sort of thing as Bash, and for the same reason. (It appears to be an execv(2)
call from texec()
in the Thompson shell and an execve()
call from execs()
in the Bourne shell's service.c
module.)
So when a command is fired from a shell, fork() inherits a child
process of it and exec() loads the child process to the memory and
executes.
Not quite. fork()
clones the current process, creating an identical child. exec()
loads a new program into the current process, replacing the existing one.
My qs is:
If the child process contains all the attributes of the parent process(which is the original process), then what is the need of this
child process? The original process also could have been loaded to the
memory.
The need is because the parent process does not want to terminate yet; it wants a new process to go off and do something at the same time that it continues to execute as well.
Does this fork and exec concept apply to all the executable program in
UNIX?Like for shell script also or only for commands? Does it also
apply for shell builtin commands?
For external commands, the shell does a fork()
so that the command runs in a new process. Builtins are just run by the shell directly. Another notable command is exec
, which tells the shell to exec()
the external program without first fork()
ing. This means that the shell itself is replaced with the new program, and so is no longer there for that program to return to when it exits. If you say, exec true
, then /bin/true
will replace your shell, and immediately exit, leaving nothing running in your terminal anymore, so it will close.
when copy on write concept is used if I'll execute a command/script?
Back in the stone age, fork()
actually had to copy all of the memory in the calling process to the new process. Copy on Write is an optimization where the page tables are set up so that the two processes start off sharing all of the same memory, and only the pages that are written to by either process are copied when needed.
Best Answer
Yes, the
exec
builtin ultimately makes use of one of theexec*()
family of system calls. So does running commands normally. It's just that when you useexec
, it doesn't use thefork()
system call first to create a new process, and the result is that the new command replaces the shell.