The UNIX Time-Sharing System*
D. M. Ritchie and K. Thompson
ABSTRACT
UNIX- is a general-purpose, multi-user,
interactive operating system for the larger Digi-
tal Equipment Corporation PDP-11 and the Interdata
8/32 computers. It offers a number of features
seldom found even in larger operating systems,
including
i A hierarchical file system incorporating
demountable volumes,
ii Compatible file, device, and inter-process
I/O,
iii The ability to initiate asynchronous
processes,
iv System command language selectable on a per-
user basis,
v Over 100 subsystems including a dozen
languages,
vi High degree of portability.
This paper discusses the nature and implementation
of the file system and of the user command inter-
face.
_________________________
* Copyright 1974, Association for Computing Machinery,
Inc., reprinted by permission. This is a revised ver-
sion of an article that appeared in Communications of
the ACM, 17, No. 7 (July 1974), pp. 365-375. That ar-
ticle was a revised version of a paper presented at the
Fourth ACM Symposium on Operating Systems Principles,
IBM Thomas J. Watson Research Center, Yorktown Heights,
New York, October 15-17, 1973.
- UNIX is a trademark of Bell Laboratories.
January 30, 1994
- 2 -
1. INTRODUCTION
There have been four versions of the UNIX time-sharing
system. The earliest (circa 1969-70) ran on the Digital
Equipment Corporation PDP-7 and -9 computers. The second
version ran on the unprotected PDP-11/20 computer. The
third incorporated multiprogramming and ran on the PDP-
11/34, /40, /45, /60, and /70 computers; it is the one
described in the previously published version of this paper,
and is also the most widely used today. This paper
describes only the fourth, current system that runs on the
PDP-11/70 and the Interdata 8/32 computers. In fact, the
differences among the various systems is rather small; most
of the revisions made to the originally published version of
this paper, aside from those concerned with style, had to do
with details of the implementation of the file system.
Since PDP-11 UNIX became operational in February, 1971,
over 600 installations have been put into service. Most of
them are engaged in applications such as computer science
education, the preparation and formatting of documents and
other textual material, the collection and processing of
trouble data from various switching machines within the Bell
System, and recording and checking telephone service orders.
Our own installation is used mainly for research in operat-
ing systems, languages, computer networks, and other topics
in computer science, and also for document preparation.
Perhaps the most important achievement of UNIX is to
demonstrate that a powerful operating system for interactive
use need not be expensive either in equipment or in human
effort: it can run on hardware costing as little as $40,000,
and less than two man-years were spent on the main system
software. We hope, however, that users find that the most
important characteristics of the system are its simplicity,
elegance, and ease of use.
Besides the operating system proper, some major pro-
grams available under UNIX are
C compiler
Text editor based on QED[1]
Assembler, linking loader, symbolic debugger
Phototypesetting and equation setting programs[2,3]
Dozens of languages including Fortran 77,
Basic, Snobol, APL, Algol 68, M6, TMG, Pas-
cal
There is a host of maintenance, utility, recreation and
novelty programs, all written locally. The UNIX user com-
munity, which numbers in the thousands, has contributed many
more programs and languages. It is worth noting that the
system is totally self-supporting. All UNIX software is
maintained on the system; likewise, this paper and all other
January 30, 1994
- 3 -
documents in this issue were generated and formatted by the
UNIX editor and text formatting programs.
II. HARDWARE AND SOFTWARE ENVIRONMENT
The PDP-11/70 on which the Research UNIX system is
installed is a 16-bit word (8-bit byte) computer with 768K
bytes of core memory; the system kernel occupies 90K bytes
about equally divided between code and data tables. This
system, however, includes a very large number of device
drivers and enjoys a generous allotment of space for I/O
buffers and system tables; a minimal system capable of run-
ning the software mentioned above can require as little as
96K bytes of core altogether. There are even larger instal-
lations; see the description of the PWB/UNIX systems,[4,3]
for example. There are also much smaller, though somewhat
restricted, versions of the system.[3]
Our own PDP-11 has two 200-Mb moving-head disks for
file system storage and swapping. There are 20 variable-
speed communications interfaces attached to 300- and 1200-
baud data sets, and an additional 12 communication lines
hard-wired to 9600-baud terminals and satellite computers.
There are also several 2400- and 4800-baud synchronous com-
munication interfaces used for machine-to-machine file
transfer. Finally, there is a variety of miscellaneous dev-
ices including nine-track magnetic tape, a line printer, a
voice synthesizer, a phototypesetter, a digital switching
network, and a chess machine.
The preponderance of UNIX software is written in the
abovementioned C language.[5] Early versions of the operat-
ing system were written in assembly language, but during the
summer of 1973, it was rewritten in C. The size of the new
system was about one-third greater than that of the old.
Since the new system not only became much easier to under-
stand and to modify but also included many functional
improvements, including multiprogramming and the ability to
share reentrant code among several user programs, we con-
sider this increase in size quite acceptable.
III. THE FILE SYSTEM
The most important role of the system is to provide a
file system. From the point of view of the user, there are
three kinds of files: ordinary disk files, directories, and
special files.
3.1 Ordinary files
A file contains whatever information the user places on
it, for example, symbolic or binary (object) programs. No
particular structuring is expected by the system. A file of
text consists simply of a string of characters, with lines
January 30, 1994
- 4 -
demarcated by the newline character. Binary programs are
sequences of words as they will appear in core memory when
the program starts executing. A few user programs manipu-
late files with more structure; for example, the assembler
generates, and the loader expects, an object file in a par-
ticular format. However, the structure of files is con-
trolled by the programs that use them, not by the system.
3.2 Directories
Directories provide the mapping between the names of
files and the files themselves, and thus induce a structure
on the file system as a whole. Each user has a directory of
his own files; he may also create subdirectories to contain
groups of files conveniently treated together. A directory
behaves exactly like an ordinary file except that it cannot
be written on by unprivileged programs, so that the system
controls the contents of directories. However, anyone with
appropriate permission may read a directory just like any
other file.
The system maintains several directories for its own
use. One of these is the root directory. All files in the
system can be found by tracing a path through a chain of
directories until the desired file is reached. The starting
point for such searches is often the root. Other system
directories contain all the programs provided for general
use; that is, all the commands. As will be seen, however,
it is by no means necessary that a program reside in one of
these directories for it to be executed.
Files are named by sequences of 14 or fewer characters.
When the name of a file is specified to the system, it may
be in the form of a path name, which is a sequence of direc-
tory names separated by slashes, ``/'', and ending in a file
name. If the sequence begins with a slash, the search
begins in the root directory. The name /alpha/beta/gamma
causes the system to search the root for directory alpha,
then to search alpha for beta, finally to find gamma in
beta. gamma may be an ordinary file, a directory, or a spe-
cial file. As a limiting case, the name ``/'' refers to the
root itself.
A path name not starting with ``/'' causes the system
to begin the search in the user's current directory. Thus,
the name alpha/beta specifies the file named beta in sub-
directory alpha of the current directory. The simplest kind
of name, for example, alpha, refers to a file that itself is
found in the current directory. As another limiting case,
the null file name refers to the current directory.
The same non-directory file may appear in several
directories under possibly different names. This feature is
called linking; a directory entry for a file is sometimes
January 30, 1994
- 5 -
called a link. The UNIX system differs from other systems
in which linking is permitted in that all links to a file
have equal status. That is, a file does not exist within a
particular directory; the directory entry for a file con-
sists merely of its name and a pointer to the information
actually describing the file. Thus a file exists indepen-
dently of any directory entry, although in practice a file
is made to disappear along with the last link to it.
Each directory always has at least two entries. The
name ``.'' in each directory refers to the directory itself.
Thus a program may read the current directory under the name
``.'' without knowing its complete path name. The name
``..'' by convention refers to the parent of the directory
in which it appears, that is, to the directory in which it
was created.
The directory structure is constrained to have the form
of a rooted tree. Except for the special entries ``.'' and
``..'', each directory must appear as an entry in exactly
one other directory, which is its parent. The reason for
this is to simplify the writing of programs that visit sub-
trees of the directory structure, and more important, to
avoid the separation of portions of the hierarchy. If arbi-
trary links to directories were permitted, it would be quite
difficult to detect when the last connection from the root
to a directory was severed.
3.3 Special files
Special files constitute the most unusual feature of
the UNIX file system. Each supported I/O device is associ-
ated with at least one such file. Special files are read
and written just like ordinary disk files, but requests to
read or write result in activation of the associated device.
An entry for each special file resides in directory /dev,
although a link may be made to one of these files just as it
may to an ordinary file. Thus, for example, to write on a
magnetic tape one may write on the file /dev/mt. Special
files exist for each communication line, each disk, each
tape drive, and for physical main memory. Of course, the
active disks and the memory special file are protected from
indiscriminate access.
There is a threefold advantage in treating I/O devices
this way: file and device I/O are as similar as possible;
file and device names have the same syntax and meaning, so
that a program expecting a file name as a parameter can be
passed a device name; finally, special files are subject to
the same protection mechanism as regular files.
3.4 Removable file systems
Although the root of the file system is always stored
January 30, 1994
- 6 -
on the same device, it is not necessary that the entire file
system hierarchy reside on this device. There is a mount
system request with two arguments: the name of an existing
ordinary file, and the name of a special file whose associ-
ated storage volume (e.g., a disk pack) should have the
structure of an independent file system containing its own
directory hierarchy. The effect of mount is to cause refer-
ences to the heretofore ordinary file to refer instead to
the root directory of the file system on the removable
volume. In effect, mount replaces a leaf of the hierarchy
tree (the ordinary file) by a whole new subtree (the hierar-
chy stored on the removable volume). After the mount, there
is virtually no distinction between files on the removable
volume and those in the permanent file system. In our
installation, for example, the root directory resides on a
small partition of one of our disk drives, while the other
drive, which contains the user's files, is mounted by the
system initialization sequence. A mountable file system is
generated by writing on its corresponding special file. A
utility program is available to create an empty file system,
or one may simply copy an existing file system.
There is only one exception to the rule of identical
treatment of files on different devices: no link may exist
between one file system hierarchy and another. This res-
triction is enforced so as to avoid the elaborate bookkeep-
ing that would otherwise be required to assure removal of
the links whenever the removable volume is dismounted.
3.5 Protection
Although the access control scheme is quite simple, it
has some unusual features. Each user of the system is
assigned a unique user identification number. When a file
is created, it is marked with the user ID of its owner.
Also given for new files is a set of ten protection bits.
Nine of these specify independently read, write, and execute
permission for the owner of the file, for other members of
his group, and for all remaining users.
If the tenth bit is on, the system will temporarily
change the user identification (hereafter, user ID) of the
current user to that of the creator of the file whenever the
file is executed as a program. This change in user ID is
effective only during the execution of the program that
calls for it. The set-user-ID feature provides for
privileged programs that may use files inaccessible to other
users. For example, a program may keep an accounting file
that should neither be read nor changed except by the pro-
gram itself. If the set-user-ID bit is on for the program,
it may access the file although this access might be forbid-
den to other programs invoked by the given program's user.
Since the actual user ID of the invoker of any program is
always available, set-user-ID programs may take any measures
January 30, 1994
- 7 -
desired to satisfy themselves as to their invoker's creden-
tials. This mechanism is used to allow users to execute the
carefully written commands that call privileged system
entries. For example, there is a system entry invokable
only by the ``super-user'' (below) that creates an empty
directory. As indicated above, directories are expected to
have entries for ``.'' and ``..''. The command which
creates a directory is owned by the super-user and has the
set-user-ID bit set. After it checks its invoker's authori-
zation to create the specified directory, it creates it and
makes the entries for ``.'' and ``..''.
Because anyone may set the set-user-ID bit on one of
his own files, this mechanism is generally available without
administrative intervention. For example, this protection
scheme easily solves the MOO accounting problem posed by
``Aleph-null.''[6]
The system recognizes one particular user ID (that of
the ``super-user'') as exempt from the usual constraints on
file access; thus (for example), programs may be written to
dump and reload the file system without unwanted interfer-
ence from the protection system.
3.6 I/O calls
The system calls to do I/O are designed to eliminate
the differences between the various devices and styles of
access. There is no distinction between ``random'' and
``sequential'' I/O, nor is any logical record size imposed
by the system. The size of an ordinary file is determined
by the number of bytes written on it; no predetermination of
the size of a file is necessary or possible.
To illustrate the essentials of I/O, some of the basic
calls are summarized below in an anonymous language that
will indicate the required parameters without getting into
the underlying complexities. Each call to the system may
potentially result in an error return, which for simplicity
is not represented in the calling sequence.
To read or write a file assumed to exist already, it
must be opened by the following call:
filep = open(name, flag)
where name indicates the name of the file. An arbitrary
path name may be given. The flag argument indicates whether
the file is to be read, written, or ``updated,'' that is,
read and written simultaneously.
The returned value filep is called a file descriptor.
It is a small integer used to identify the file in subse-
quent calls to read, write, or otherwise manipulate the
January 30, 1994
- 8 -
file.
To create a new file or completely rewrite an old one,
there is a create system call that creates the given file if
it does not exist, or truncates it to zero length if it does
exist; create also opens the new file for writing and, like
open, returns a file descriptor.
The file system maintains no locks visible to the user,
nor is there any restriction on the number of users who may
have a file open for reading or writing. Although it is
possible for the contents of a file to become scrambled when
two users write on it simultaneously, in practice difficul-
ties do not arise. We take the view that locks are neither
necessary nor sufficient, in our environment, to prevent
interference between users of the same file. They are
unnecessary because we are not faced with large, single-file
data bases maintained by independent processes. They are
insufficient because locks in the ordinary sense, whereby
one user is prevented from writing on a file that another
user is reading, cannot prevent confusion when, for example,
both users are editing a file with an editor that makes a
copy of the file being edited.
There are, however, sufficient internal interlocks to
maintain the logical consistency of the file system when two
users engage simultaneously in activities such as writing on
the same file, creating files in the same directory, or
deleting each other's open files.
Except as indicated below, reading and writing are
sequential. This means that if a particular byte in the
file was the last byte written (or read), the next I/O call
implicitly refers to the immediately following byte. For
each open file there is a pointer, maintained inside the
system, that indicates the next byte to be read or written.
If n bytes are read or written, the pointer advances by n
bytes.
Once a file is open, the following calls may be used:
n = read(filep, buffer, count)
n = write(filep, buffer, count)
Up to count bytes are transmitted between the file specified
by filep and the byte array specified by buffer. The
returned value n is the number of bytes actually transmit-
ted. In the write case, n is the same as count except under
exceptional conditions, such as I/O errors or end of physi-
cal medium on special files; in a read, however, n may
without error be less than count. If the read pointer is so
near the end of the file that reading count characters would
cause reading beyond the end, only sufficient bytes are
transmitted to reach the end of the file; also, typewriter-
January 30, 1994
- 9 -
like terminals never return more than one line of input.
When a read call returns with n equal to zero, the end of
the file has been reached. For disk files this occurs when
the read pointer becomes equal to the current size of the
file. It is possible to generate an end-of-file from a ter-
minal by use of an escape sequence that depends on the dev-
ice used.
Bytes written affect only those parts of a file implied
by the position of the write pointer and the count; no other
part of the file is changed. If the last byte lies beyond
the end of the file, the file is made to grow as needed.
To do random (direct-access) I/O it is only necessary
to move the read or write pointer to the appropriate loca-
tion in the file.
location = lseek(filep, offset, base)
The pointer associated with filep is moved to a position
offset bytes from the beginning of the file, from the
current position of the pointer, or from the end of the
file, depending on base. offset may be negative. For some
devices (e.g., paper tape and terminals) seek calls are
ignored. The actual offset from the beginning of the file
to which the pointer was moved is returned in location.
There are several additional system entries having to
do with I/O and with the file system that will not be dis-
cussed. For example: close a file, get the status of a
file, change the protection mode or the owner of a file,
create a directory, make a link to an existing file, delete
a file.
IV. IMPLEMENTATION OF THE FILE SYSTEM
As mentioned in Section 3.2 above, a directory entry
contains only a name for the associated file and a pointer
to the file itself. This pointer is an integer called the
i-number (for index number) of the file. When the file is
accessed, its i-number is used as an index into a system
table (the i-list) stored in a known part of the device on
which the directory resides. The entry found thereby (the
file's i-node) contains the description of the file:
i the user and group-ID of its owner
ii its protection bits
iii the physical disk or tape addresses for the file con-
tents
iv its size
January 30, 1994
- 10 -
v time of creation, last use, and last modification
vi the number of links to the file, that is, the number of
times it appears in a directory
vii a code indicating whether the file is a directory, an
ordinary file, or a special file.
The purpose of an open or create system call is to turn the
path name given by the user into an i-number by searching
the explicitly or implicitly named directories. Once a file
is open, its device, i-number, and read/write pointer are
stored in a system table indexed by the file descriptor
returned by the open or create. Thus, during a subsequent
call to read or write the file, the descriptor may be easily
related to the information necessary to access the file.
When a new file is created, an i-node is allocated for
it and a directory entry is made that contains the name of
the file and the i-node number. Making a link to an exist-
ing file involves creating a directory entry with the new
name, copying the i-number from the original file entry, and
incrementing the link-count field of the i-node. Removing
(deleting) a file is done by decrementing the link-count of
the i-node specified by its directory entry and erasing the
directory entry. If the link-count drops to 0, any disk
blocks in the file are freed and the i-node is de-allocated.
The space on all disks that contain a file system is
divided into a number of 512-byte blocks logically addressed
from 0 up to a limit that depends on the device. There is
space in the i-node of each file for 13 device addresses.
For nonspecial files, the first 10 device addresses point at
the first 10 blocks of the file. If the file is larger than
10 blocks, the 11 device address points to an indirect block
containing up to 128 addresses of additional blocks in the
file. Still larger files use the twelfth device address of
the i-node to point to a double-indirect block naming 128
indirect blocks, each pointing to 128 blocks of the file.
If required, the thirteenth device address is a triple-
indirect block. Thus files may conceptually grow to
[(10+128+1282+1283).512] bytes. Once opened, bytes numbered
below 5120 can be read with a single disk access; bytes in
the range 5120 to 70,656 require two accesses; bytes in the
range 70,656 to 8,459,264 require three accesses; bytes from
there to the largest file (1,082,201,088) require four
accesses. In practice, a device cache mechanism (see below)
proves effective in eliminating most of the indirect
fetches.
The foregoing discussion applies to ordinary files.
When an I/O request is made to a file whose i-node indicates
that it is special, the last 12 device address words are
immaterial, and the first specifies an internal device name,
January 30, 1994
- 11 -
which is interpreted as a pair of numbers representing,
respectively, a device type and subdevice number. The dev-
ice type indicates which system routine will deal with I/O
on that device; the subdevice number selects, for example, a
disk drive attached to a particular controller or one of
several similar terminal interfaces.
In this environment, the implementation of the mount
system call (Section 3.4) is quite straightforward. mount
maintains a system table whose argument is the i-number and
device name of the ordinary file specified during the mount,
and whose corresponding value is the device name of the
indicated special file. This table is searched for each i-
number/device pair that turns up while a path name is being
scanned during an open or create; if a match is found, the
i-number is replaced by the i-number of the root directory
and the device name is replaced by the table value.
To the user, both reading and writing of files appear
to be synchronous and unbuffered. That is, immediately
after return from a read call the data are available; con-
versely, after a write the user's workspace may be reused.
In fact, the system maintains a rather complicated buffering
mechanism that reduces greatly the number of I/O operations
required to access a file. Suppose a write call is made
specifying transmission of a single byte. The system will
search its buffers to see whether the affected disk block
currently resides in main memory; if not, it will be read in
from the device. Then the affected byte is replaced in the
buffer and an entry is made in a list of blocks to be writ-
ten. The return from the write call may then take place,
although the actual I/O may not be completed until a later
time. Conversely, if a single byte is read, the system
determines whether the secondary storage block in which the
byte is located is already in one of the system's buffers;
if so, the byte can be returned immediately. If not, the
block is read into a buffer and the byte picked out.
The system recognizes when a program has made accesses
to sequential blocks of a file, and asynchronously pre-reads
the next block. This significantly reduces the running time
of most programs while adding little to system overhead.
A program that reads or writes files in units of 512
bytes has an advantage over a program that reads or writes a
single byte at a time, but the gain is not immense; it comes
mainly from the avoidance of system overhead. If a program
is used rarely or does no great volume of I/O, it may quite
reasonably read and write in units as small as it wishes.
The notion of the i-list is an unusual feature of UNIX.
In practice, this method of organizing the file system has
proved quite reliable and easy to deal with. To the system
itself, one of its strengths is the fact that each file has
January 30, 1994
- 12 -
a short, unambiguous name related in a simple way to the
protection, addressing, and other information needed to
access the file. It also permits a quite simple and rapid
algorithm for checking the consistency of a file system, for
example, verification that the portions of each device con-
taining useful information and those free to be allocated
are disjoint and together exhaust the space on the device.
This algorithm is independent of the directory hierarchy,
because it need only scan the linearly organized i-list. At
the same time the notion of the i-list induces certain pecu-
liarities not found in other file system organizations. For
example, there is the question of who is to be charged for
the space a file occupies, because all directory entries for
a file have equal status. Charging the owner of a file is
unfair in general, for one user may create a file, another
may link to it, and the first user may delete the file. The
first user is still the owner of the file, but it should be
charged to the second user. The simplest reasonably fair
algorithm seems to be to spread the charges equally among
users who have links to a file. Many installations avoid
the issue by not charging any fees at all.
V. PROCESSES AND IMAGES
An image is a computer execution environment. It
includes a memory image, general register values, status of
open files, current directory and the like. An image is the
current state of a pseudo-computer.
A process is the execution of an image. While the pro-
cessor is executing on behalf of a process, the image must
reside in main memory; during the execution of other
processes it remains in main memory unless the appearance of
an active, higher-priority process forces it to be swapped
out to the disk.
The user-memory part of an image is divided into three
logical segments. The program text segment begins at loca-
tion 0 in the virtual address space. During execution, this
segment is write-protected and a single copy of it is shared
among all processes executing the same program. At the
first hardware protection byte boundary above the program
text segment in the virtual address space begins a non-
shared, writable data segment, the size of which may be
extended by a system call. Starting at the highest address
in the virtual address space is a stack segment, which
automatically grows downward as the stack pointer fluctu-
ates.
5.1 Processes
Except while the system is bootstrapping itself into
operation, a new process can come into existence only by use
of the fork system call:
January 30, 1994
- 13 -
processid = fork()
When fork is executed, the process splits into two indepen-
dently executing processes. The two processes have indepen-
dent copies of the original memory image, and share all open
files. The new processes differ only in that one is con-
sidered the parent process: in the parent, the returned
processid actually identifies the child process and is never
0, while in the child, the returned value is always 0.
Because the values returned by fork in the parent and
child process are distinguishable, each process may deter-
mine whether it is the parent or child.
5.2 Pipes
Processes may communicate with related processes using
the same system read and write calls that are used for
file-system I/O. The call:
filep = pipe()
returns a file descriptor filep and creates an inter-process
channel called a pipe. This channel, like other open files,
is passed from parent to child process in the image by the
fork call. A read using a pipe file descriptor waits until
another process writes using the file descriptor for the
same pipe. At this point, data are passed between the
images of the two processes. Neither process need know that
a pipe, rather than an ordinary file, is involved.
Although inter-process communication via pipes is a
quite valuable tool (see Section 6.2), it is not a com-
pletely general mechanism, because the pipe must be set up
by a common ancestor of the processes involved.
5.3 Execution of programs
Another major system primitive is invoked by
execute(file, arg , arg , ... , arg )
1 2 n
which requests the system to read in and execute the program
named by file, passing it string arguments arg , arg , ...,
arg . All the code and data in the process invoking execute
is nreplaced from the file, but open files, current direc-
tory, and inter-process relationships are unaltered. Only
if the call fails, for example because file could not be
found or because its execute-permission bit was not set,
does a return take place from the execute primitive; it
resembles a ``jump'' machine instruction rather than a sub-
routine call.
January 30, 1994
- 14 -
5.4 Process synchronization
Another process control system call:
processid = wait(status)
causes its caller to suspend execution until one of its
children has completed execution. Then wait returns the
processid of the terminated process. An error return is
taken if the calling process has no descendants. Certain
status from the child process is also available.
5.5 Termination
Lastly:
exit(status)
terminates a process, destroys its image, closes its open
files, and generally obliterates it. The parent is notified
through the wait primitive, and status is made available to
it. Processes may also terminate as a result of various
illegal actions or user-generated signals (Section VII
below).
VI. THE SHELL
For most users, communication with the system is car-
ried on with the aid of a program called the shell. The
shell is a command-line interpreter: it reads lines typed by
the user and interprets them as requests to execute other
programs. (The shell is described fully elsewhere,[3] so
this section will discuss only the theory of its operation.)
In simplest form, a command line consists of the command
name followed by arguments to the command, all separated by
spaces:
command arg arg ... arg
1 2 n
The shell splits up the command name and the arguments into
separate strings. Then a file with name command is sought;
command may be a path name including the ``/'' character to
specify any file in the system. If command is found, it is
brought into memory and executed. The arguments collected
by the shell are accessible to the command. When the com-
mand is finished, the shell resumes its own execution, and
indicates its readiness to accept another command by typing
a prompt character.
If file command cannot be found, the shell generally
prefixes a string such as /bin/ to command and attempts
again to find the file. Directory /bin contains commands
intended to be generally used. (The sequence of directories
to be searched may be changed by user request.)
January 30, 1994
- 15 -
6.1 Standard I/O
The discussion of I/O in Section III above seems to
imply that every file used by a program must be opened or
created by the program in order to get a file descriptor for
the file. Programs executed by the shell, however, start
off with three open files with file descriptors 0, 1, and 2.
As such a program begins execution, file 1 is open for writ-
ing, and is best understood as the standard output file.
Except under circumstances indicated below, this file is the
user's terminal. Thus programs that wish to write informa-
tive information ordinarily use file descriptor 1. Con-
versely, file 0 starts off open for reading, and programs
that wish to read messages typed by the user read this file.
The shell is able to change the standard assignments of
these file descriptors from the user's terminal printer and
keyboard. If one of the arguments to a command is prefixed
by ``>'', file descriptor 1 will, for the duration of the
command, refer to the file named after the ``>''. For exam-
ple:
ls
ordinarily lists, on the typewriter, the names of the files
in the current directory. The command:
ls >there
creates a file called there and places the listing there.
Thus the argument >there means ``place output on there.'' On
the other hand:
ed
ordinarily enters the editor, which takes requests from the
user via his keyboard. The command
ed