next up previous
Next: Macro Substitution Up: Command Interpreters Previous: Built-In vs Separate

Built-In vs User-defined Commands

A command may be built-in, or user-defined. A user-defined command names a utility program that is executed to process the command. For instance the command `cd' is built-in and processed entirely by the command interpreter, while the command `ls' results in the execution of the `ls' program. The arguments of user-defined commands are interpreted by the invoked programs.

For each user-defined command, the command interpreter asks the operating system to create a new process executing the specified program. The command interpreter may wait for the child process to terminate before accepting another command, in which case we say the child process has been created in foreground, or start the new process and accept the new command while the child process is executing, in which case we say the child process is executing in background. The user is given the option to specify whether a command should be executed in the background or foreground. For instance, in Unix, the command:

cc prog.c
executes the compiler in foreground, while the command
cc prog.c &
executes the compiler in background.

Why support both background and foreground processes? Background processes are useful for starting several activities, for instance editing and compiling, concurrently. Foreground processes are useful for waiting for an activity to start before beginning another. For instance, a user would want the following commands executed sequentially:

chmod 740 prog.c
ls
In systems that do not support windows, a user may want the interactive processes
mail
edit foo
to be executed sequentially, in order to enforce `mutual exclusion' on the input and output streams.

How does a command interpreter create new processes and wait for their termination?

The following pseudo code illustrates how this is done in Unix.

loop
   GetCommand (object_file, parameters)
   (* execute the program specified in object_file} *)
   if fork() = 0 then (* child process *)
       exec (object_file, parameters)
   elsif foregroundDesired  then 
       wait()
end
The fork call creates a child process that is identical to the calling process in the sense that it gets a copy of the core image and the open file table of the calling process. The call returns the process id of the child process in the parent process, and the id 0 in the child process. This return value is used by the two processes to do different activities: The child process executes the system call exec (object_file), which replaces the core image of the calling process with the contents of object_file. The parent process either waits for the child process to terminate or directly processes the next command, depending on whether a foreground or background process is desired.

next up previous
Next: Macro Substitution Up: Command Interpreters Previous: Built-In vs Separate



Prasun Dewan
Thu Mar 28 12:06:42 EST 2002