1.4. Processes and the Shell

1.4.1. What Is a Process?

A process is a program in execution and can be identified by its unique PID (process identification) number. The kernel controls and manages processes. A process consists of the executable program, its data and stack, program and stack pointer, registers, and all the information needed for the program to run. When you log in, the process running is normally a shell (bash)[5], called the login shell. The shell belongs to a process group identified by the group's PID. Only one process group has control of the terminal at a time and is said to be running in the foreground. When you log on, your shell is in control of the terminal and waits for you to type a command at the prompt. On Linux systems, the shell will normally start up another process, xinit, to launch the X Windowing system. After X Windows starts, a window manager process (twm, fvwm, etc.) is executed, providing a virtual desktop.[6] Then from a pop-up menu, you can start up a number of other processes, such as xterm (gets a terminal), xman (provides manual pages), or emacs (starts a text editor). Multiple processes are running and monitored by the Linux kernel, allocating each of the processes a little slice of the CPU in a way that is unnoticeable to the user.

[5] The default Linux shell is bash, the Bourne Again shell.

[6] A number of desktop environments come with Linux, including Gnome, KDE, X, etc.

1.4.2. What Is a System Call?

The shell can spawn (create) other processes. In fact, when you enter a command at the prompt or from a shell script, the shell has the responsibility of finding the command either in its internal code (built-in) or out on the disk, and then arranging for the command to be executed. This is done with calls to the kernel, called system calls. A system call is a request for kernel services and the only way a process can access the system's hardware. There are a number of system calls that allow processes to be created, executed, and terminated. (The shell provides other services from the kernel when it performs redirection and piping, command substitution, and the execution of user commands.) The system calls used by the shell to cause new processes to run are discussed in the following sections. See Figure 1.2.

Figure 1.2. The shell and command execution.


1.4.3. What Processes Are Running?

The ps Command

The ps command with its many options displays a list of the processes currently running in a number of formats. The following example shows all processes that are running by users on a Linux system. (See Appendix A for ps and its options.)

Example 1.2.
$ ps au
							(Linux ps)
USER       PID %CPU %MEM  SIZE   RSS TTY STAT START   TIME COMMAND
ellie      456  0.0  1.3  1268   840   1 S    13:23   0:00 -bash 
ellie      476  0.0  1.0  1200   648   1 S    13:23   0:00 sh
/usr/X11R6/bin/sta
ellie      478  0.0  1.0  2028   676   1 S    13:23   0:00 xinit
/home/ellie/.xi
ellie      480  0.0  1.6  1852  1068   1 S    13:23   0:00 fvwm2 
ellie      483  0.0  1.3  1660   856   1 S    13:23   0:00
/usr/X11R6/lib/X11/fv
ellie      484  0.0  1.3  1696   868   1 S    13:23   0:00
/usr/X11R6/lib/X11/fv
ellie      487  0.0  2.0  2348  1304   1 S    13:23   0:00 xclock -bg
#c0c0c0 -p
ellie      488  0.0  1.1  1620   724   1 S    13:23   0:00
/usr/X11R6/lib/X11/fv
ellie      489  0.0  2.0  2364  1344   1 S    13:23   0:00 xload -
nolabel -bg gr
ellie      495  0.0  1.3  1272   848  p0 S    13:24   0:00 -bash 
ellie      797  0.0  0.7   852   484  p0 R    14:03   0:00 ps au 
root       457  0.0  0.4   724   296   2 S    13:23   0:00
/sbin/mingetty tty2 
root       458  0.0  0.4   724   296   3 S    13:23   0:00
/sbin/mingetty tty3 
root       459  0.0  0.4   724   296   4 S    13:23   0:00
/sbin/mingetty tty4 
root       460  0.0  0.4   724   296   5 S    13:23   0:00
/sbin/mingetty tty5 
root       461  0.0  0.4   724   296   6 S    13:23   0:00
/sbin/mingetty tty6 
root       479  0.0  4.5 12092  2896   1 S    13:23   0:01 X :0 
root       494  0.0  2.5  2768  1632   1 S    13:24   0:00 nxterm
							-ls -sb -fn
						

The pstree Command

Another way to see what processes are running and what processes are child processes is to use the Linux pstree command. The pstree command displays all processes as a tree with its root being the first process that runs, called init. If a user name is specified, then that user's processes are at the root of the tree. If a process spawns more than one process of the same name, pstree visually merges the identical branches by putting them in square brackets and prefixing them with the number of times the processes is repeated. To illustrate, in the following example, the httpd server process has started up 10 child processes. (See Appendix A for list of pstree options.)

Example 1.3.
							pstree
init---4*[getty]
init-+-atd
     |-bash---startx---xinit-+-X
     |                       `-fvwm2-+-FvwmButtons
     |                               |-FvwmPager
     |                               `-FvwmTaskBar
     |-cardmgr
     |-crond
     |-gpm
     |-httpd---10*[httpd]
     |-ifup-ppp---pppd---chat
     |-inetd
     |-kerneld
     |-kflushd
     |-klogd
     |-kswapd
     |-lpd
     |-2*[md_thread]
     |-5*[mingetty]

               |-nmbd
     |-nxterm---bash---tcsh---pstree
     |-portmap
     |-sendmail
     |-smbd
     |-syslogd
     |-update
     |-xclock
     `-xload

1.4.4. System Calls for Creating and Terminating Processes

The fork System Call

A new process is created with the fork system call. The fork system call creates a duplicate of the calling process. The new process is called the child and the process that created it is called the parent. The child process starts running right after the call to fork, and both processes initially share the CPU. The child process has a copy of the parent's environment, open files, real and user identifications, umask, current working directory, and signals.

When you type a command, the shell parses the command line and determines whether or not the first word is a built-in command or an executable program. If the command is built-in, the shell handles it, but if not, the shell invokes the fork system call to make a copy of itself (see Figure 1.3). Its child will search the path to find the command, as well as set up the file descriptors for redirection, pipes, command substitution, and background processing. While the child shell works, the parent normally sleeps. (See "The wait System Call" below.)

Figure 1.3. The fork system call.


The wait System Call

The parent shell is programmed to go to sleep (wait) while the child takes care of details such as handling redirection, pipes, and background processing. The wait system call causes the parent process to suspend until one of its children terminates. If wait is successful, it returns the PID of the child that died and the child's exit status. If the parent does not wait and the child exits, the child is put in a zombie state (suspended animation) and will stay in that state until either the parent calls wait or the parent dies.[7] If the parent dies before the child, the init process adopts any orphaned zombie process. The wait system call, then, is not just used to put a parent to sleep, but to ensure that the process terminates properly.

[7] To remove zombie processes, the system must be rebooted.

The exec System Call

After you enter a command at the terminal, the shell normally forks off a new shell process: the child process. As mentioned earlier, the child shell is responsible for causing the command you typed to be executed. It does this by calling the exec system call. Remember, the user command is really just an executable program. The shell searches the path for the new program. If it is found, the shell calls the exec system call with the name of the command as its argument. The kernel loads this new program into memory in place of the shell that called it. The child shell, then, is overlaid with the new program. The new program becomes the child process and starts executing. Although the new process has its own local variables, all environment variables, open files, signals, and the current working directory are passed to the new process. This process exits when it has finished, and the parent shell wakes up.

The exit System Call

A program can terminate at any time by executing the exit call. When a child process terminates, it sends a signal (sigchild) and waits for the parent to accept its exit status. The exit status is a number between 0 and 255.[8] An exit status of zero indicates that the program executed successfully, and a nonzero exit status means that the program failed in some way.

[8] If the program is terminated by a signal, its return value is 128 + n, where n is the signal number.

For example, if the command ls had been typed at the command line, the parent shell would fork a child process and go to sleep. The child shell would then exec (overlay) the ls program. The ls program would run in place of the child, inheriting all the environment variables, open files, user information, and state information. When the process (ls) finished execution, it would exit and the parent shell would wake up. A prompt would appear on the screen, and the shell would wait for another command. If you are interested in knowing how a command exited, each shell has a special built-in variable that contains the exit status of the last command that terminated. (All of this will be explained in detail in the individual shell chapters.) See Figure 1.4 on page15 for an example of process creation and termination.

Example 1.4.
  (C and TC Shell)
1  > cp filex filey
   > echo $status
   0
2  > cp xyz
							Usage: cp [-ip] f1 f2; or: cp [-ipr] f1 … fn d2
   > echo $status
   1
   (Tcsh, Bourne, Korn, and Bash Shells)
3  $ cp filex filey
   $ echo $?
   0
   $ cp xyz
							Usage: cp [-ip] f1 f2; or: cp [-ipr] f1 … fn d2
   $ echo $?
   1

Explanation

  1. The cp (copy) command is entered at the TC shell command line prompt (>). After the command has made a copy of filex called filey, the program exits and the prompt appears. The tcsh status variable contains the exit status of the last command that was executed. If the status is zero, the cp program exited with success. If the exit status is nonzero, the cp program failed in some way.

  2. When entering the cp command, the user failed to provide two filenames: the source and destination files. The cp program sent an error message to the screen, and exited, with a status of one. That number is stored in the tcsh status variable. Any number other than zero indicates that the program failed.

  3. The Tcsh, Bourne, Bash, and Korn shells process the cp command as the TC shell did in the first two examples. The only difference is that the Bourne and Korn shells store the exit status in the ? variable, rather than the status variable.[a]

    [a] The TC shell provides both the status and ? variables for holding exit status.

Figure 1.4. The fork, exec, wait, and exit system calls. See following Explanation.


Explanation

  1. The parent shell creates a copy of itself with the fork system call. The copy is called the child shell.

  2. The child shell has a new PID and is a copy of its parent. It will share the CPU with the parent.

  3. The kernel loads the grep program into memory and executes (exec) it in place of the child shell. The grep program inherits the open files and environment from the child.

  4. The grep program exits, the kernel cleans up, and the parent is awakened.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.18.198