- Please explain the exec() function and its family
- 7 Answers 7
- Exec function in linux
- NAME
- SYNOPSIS
- DESCRIPTION
- OPTIONS
- OPERANDS
- STDIN
- INPUT FILES
- ENVIRONMENT VARIABLES
- ASYNCHRONOUS EVENTS
- STDOUT
- STDERR
- OUTPUT FILES
- EXTENDED DESCRIPTION
- EXIT STATUS
- CONSEQUENCES OF ERRORS
- APPLICATION USAGE
- EXAMPLES
- RATIONALE
- FUTURE DIRECTIONS
- SEE ALSO
- COPYRIGHT
Please explain the exec() function and its family
What is the exec() function and its family? Why is this function used and how does its work? Please anyone explain these functions.
7 Answers 7
Simplistically, in UNIX, you have the concept of processes and programs. A process is an environment in which a program executes.
The simple idea behind the UNIX «execution model» is that there are two operations you can do.
The first is to fork() , which creates a brand new process containing a duplicate (mostly) of the current program, including its state. There are a few differences between the two processes which allow them to figure out which is the parent and which is the child.
The second is to exec() , which replaces the program in the current process with a brand new program.
From those two simple operations, the entire UNIX execution model can be constructed.
To add some more detail to the above:
The use of fork() and exec() exemplifies the spirit of UNIX in that it provides a very simple way to start new processes.
The fork() call makes a near duplicate of the current process, identical in almost every way (not everything is copied over, for example, resource limits in some implementations, but the idea is to create as close a copy as possible). Only one process calls fork() but two processes return from that call — sounds bizarre but it’s really quite elegant
The new process (called the child) gets a different process ID (PID) and has the PID of the old process (the parent) as its parent PID (PPID).
Because the two processes are now running exactly the same code, they need to be able to tell which is which — the return code of fork() provides this information — the child gets 0, the parent gets the PID of the child (if the fork() fails, no child is created and the parent gets an error code).
That way, the parent knows the PID of the child and can communicate with it, kill it, wait for it and so on (the child can always find its parent process with a call to getppid() ).
The exec() call replaces the entire current contents of the process with a new program. It loads the program into the current process space and runs it from the entry point.
So, fork() and exec() are often used in sequence to get a new program running as a child of a current process. Shells typically do this whenever you try to run a program like find — the shell forks, then the child loads the find program into memory, setting up all command line arguments, standard I/O and so forth.
But they’re not required to be used together. It’s perfectly acceptable for a program to call fork() without a following exec() if, for example, the program contains both parent and child code (you need to be careful what you do, each implementation may have restrictions).
This was used quite a lot (and still is) for daemons which simply listen on a TCP port and fork a copy of themselves to process a specific request while the parent goes back to listening. For this situation, the program contains both the parent and the child code.
Similarly, programs that know they’re finished and just want to run another program don’t need to fork() , exec() and then wait()/waitpid() for the child. They can just load the child directly into their current process space with exec() .
Some UNIX implementations have an optimized fork() which uses what they call copy-on-write. This is a trick to delay the copying of the process space in fork() until the program attempts to change something in that space. This is useful for those programs using only fork() and not exec() in that they don’t have to copy an entire process space. Under Linux, fork() only makes a copy of the page tables and a new task structure, exec() will do the grunt work of «separating» the memory of the two processes.
If the exec is called following fork (and this is what happens mostly), that causes a write to the process space and it is then copied for the child process, before modifications are allowed.
Linux also has a vfork() , even more optimised, which shares just about everything between the two processes. Because of that, there are certain restrictions in what the child can do, and the parent halts until the child calls exec() or _exit() .
The parent has to be stopped (and the child is not permitted to return from the current function) since the two processes even share the same stack. This is slightly more efficient for the classic use case of fork() followed immediately by exec() .
Note that there is a whole family of exec calls ( execl , execle , execve and so on) but exec in context here means any of them.
The following diagram illustrates the typical fork/exec operation where the bash shell is used to list a directory with the ls command:
+--------+ | pid=7 | | ppid=4 | | bash | +--------+ | | calls fork V +--------+ +--------+ | pid=7 | forks | pid=22 | | ppid=4 | ----------> | ppid=7 | | bash | | bash | +--------+ +--------+ | | | waits for pid 22 | calls exec to run ls | V | +--------+ | | pid=22 | | | ppid=7 | | | ls | V +--------+ +--------+ | | pid=7 | | exits | ppid=4 |
Exec function in linux
NAME
exec - execute commands and open, close, or copy file descriptors
SYNOPSIS
exec [command [argument . ]]
DESCRIPTION
The exec utility shall open, close, and/or copy file descriptors as specified by any redirections as part of the command. If exec is specified without command or arguments, and any file descriptors with numbers greater than 2 are opened with associated redirection statements, it is unspecified whether those file descriptors remain open when the shell invokes another utility. Scripts concerned that child shells could misuse open file descriptors can always close them explicitly, as shown in one of the following examples. If exec is specified with command, it shall replace the shell with command without creating a new process. If arguments are specified, they shall be arguments to command. Redirection affects the current shell execution environment.
OPTIONS
OPERANDS
STDIN
INPUT FILES
ENVIRONMENT VARIABLES
ASYNCHRONOUS EVENTS
STDOUT
STDERR
The standard error shall be used only for diagnostic messages.
OUTPUT FILES
EXTENDED DESCRIPTION
EXIT STATUS
If command is specified, exec shall not return to the shell; rather, the exit status of the process shall be the exit status of the program implementing command, which overlaid the shell. If command is not found, the exit status shall be 127. If command is found, but it is not an executable utility, the exit status shall be 126. If a redirection error occurs (see Consequences of Shell Errors ), the shell shall exit with a value in the range 1-125. Otherwise, exec shall return a zero exit status.
CONSEQUENCES OF ERRORS
Default. The following sections are informative.
APPLICATION USAGE
EXAMPLES
Open readfile as file descriptor 3 for reading: exec 3 readfile Open writefile as file descriptor 4 for writing: exec 4> writefile Make file descriptor 5 a copy of file descriptor 0: exec 5 Close file descriptor 3: exec 3 Cat the file maggie by replacing the current shell with the cat utility: exec cat maggie
RATIONALE
Most historical implementations were not conformant in that: foo=bar exec cmd did not pass foo to cmd.
FUTURE DIRECTIONS
SEE ALSO
Special Built-In Utilities
COPYRIGHT
© 2019 Canonical Ltd. Ubuntu and Canonical are registered trademarks of Canonical Ltd.