Survey of Operating Systems:
§ 4: Software Development with UNIX

Instructor: M.S. Schmalz


Reading Assignments and Exercises

Recall our discussion in Section 1 of these Web notes about the organization of hardware and software. UNIX is frequently used for software development, due to the large number of systems that support UNIX.

This section reviews some basic utilities or programs available in UNIX that support software development tasks such as editing, compilation, linking, and loading. We have organized this section as follows:

Information in this section was compiled from a variety of text- and Web-based sources, and is not to be used for any commercial purpose.

4.1. Editors: vi and emacs

Reading Assignments and Exercises

An editor is a software tool with which one produces source code, which is then compiled and can be run on a workstation or computer. UNIX systems generally have many text-based editors associated with various programming packages, for example, Microsoft or IBM C++ or J++ development systems. However, two text-based editors are well known in the UNIX community, namely, vi and emacs. We present salient tutorials, as follows.

4.1.1. vi Editor Tutorial

We begin with a general introduction, then progress to more advanced topics. This tutorial is adapted from the vi tutorial published by the Office of Information Technology at the University of North Carolina at Chapel Hill, which is freely distributed and may be copied for individual or non-profit use. We have indexed the tutorial sections and made explanations more concise.

The vi editor (short for visual editor) is a screen editor that is available on most Unix systems. Once you have learned vi, you will find that it is a fast and powerful program. In particular, vi has no menus but instead uses combinations of keystrokes in order to accomplish commands. This helps you avoid spending (or wasting) time mousing through a large hierarchy of menu-driven commands.

4.1.2. Starting vi

To start using vi, go to the Unix prompt and type vi followed by an optional file name. We denote this command sequence is denoted as:

vi file

If you wish to edit an existing file, type its name in place of file in the preceding command sequence. Otherwise, you will be creating a new file, so you can type the name you wish to give to the new file in place of file, above. After invoking vi, a screen will appear, similar to the one below. This screen shows blank lines with tildes (~) as well as the name and status of the file.

Example. Here follows an example of an initial vi session:

Note that your screen will usually be filled with blank rows, each starting with a tilde (~), except for the bottom line.

4.1.3. vi Editor Modes

The vi editor has two modes: command mode and insert mode. When vi is in command mode, letters of the keyboard will be interpreted as commands. In insert mode, the keyboard can be used to type or edit text. Initially, vi is in command mode. A disadvantage of vi is the need to remember which mode is active, in order to correctly move between modes. To enter insert mode, type i. If you wish to leave insert mode and return to the command mode, hit the {Esc} key. If you are unsure of the current mode, depress {Esc} several times, which will return you to command mode.

4.1.3.1. Command Mode Information

As mentioned previously, vi uses keyboard characters as commands. In general, vi commands are:

Some vi commands start with a colon (:). These commands are ex commands which are used by the ex editor, since ex is an editor engine that supports the vi interface.

4.1.3.2. Entering Text

To enter text in an otherwise empty file, first change from the command mode to the insert mode by typing an i. Then, whatever you type will be entered into the file.

Additional Exercise. Invoke vi, then enter insert mode and type a few short lines, depressing {Enter} at the end of each of line.

Unlike modern word processors, vi is an older program that does not have word wrap. To correct a mistake, use the {BackSpace} key. If that feature does not work on your system, try using the {Ctrl-h} key combination.

4.1.3.3. Cursor Movement

Cursor movement occurs only in command mode. For example, if you've just typed some text, you're still in insert mode and will need to press ESC to return to the command mode.

Try using the arrow keys to move up, down, left and right in your file. If these keys do not work, then use the following keys:

If you move the cursor so as to touch the limits of the screen, the display might flash on and off briefly, or your workstation may emit a beep.

Although these direction keys can help you move through the file, it might be more efficient to use the following shortcut keys:

It is possible to precede these commands with a number for greater movement. For example, the command 5w would move you forward five words; 12b would move you backwards twelve words. [You can also use numbers with the commands mentioned earlier. For example, the command 5j would move you down 5 characters.]

In vi command mode, lower and upper case command keys are interpreted differently. For example, when using the lower case w, b, and e commands, words will be defined by a space or a punctuation mark. On the other hand, W, B, and E commands may be used to move between words also, but these commands ignore punctuation.

If you want to move quickly on a line, you can include the $ and the 0 (zero) characters in your command sequence. The $ will move you to the end of a line, while the 0 will move you quickly to the beginning of a line.

To move the cursor to a line within your current screen use the following commands:

You can scroll through a file and see other screens using the key combinations:

Two efficient (but cryptic) file movement commands are G to move to the end-of-file and 1G to move to the beginning-of-file. By preceding G with a number n, one can move to the n-th line of the current file (e.g. 15G would move you to line 15 of the current file).

4.1.3.4. Searching for Text

Searching for a specific string (text or sequence of characters) can be accomplished in command mode only by typing a slash (/) followed by the text you wish to search for. When you press {Enter}, the cursor will move to the first incidence of the specific string. You can repeat the search by typing n or search in reverse direction by using N.

4.1.4. Basic Editing

To edit a file, you must be in command mode. Recall that commands will be interpreted differently depending upon whether they are issued in lower or upper case. Similar to the G command described in Section 4.1.3.3, many editing commands can be preceded by a number to indicate repetition of the command.

4.1.4.1. Deleting Characters, Words, or Lines

To delete a character, first place the cursor on that character, then use one of the following commands:

Deletion of multiple characters is accomplished by preceding one of the above-listed deletion commands with a number.

Example. The command 10x will delete a selected character (denoted by c) as well as the next 9 characters following c:

Given the string hello dave, this is kristi, the command 10x executed on the d of dave will produce the string hello is kristi .

Additionally, the command 10X will delete 10 characters to the left of the currently selected character. The command 5dw will delete 5 words, while 4dd deletes four lines.

4.1.4.2. Pasting Deleted Text

Deleted text can be inserted (or pasted at a location of a file different from the place where the text was deleted. In vi, the put command pastes the last portion of text that was deleted. This is possible since vi stores deleted text in a paste buffer, so it can be recalled as needed. To use the put command, place the cursor where you wish the deleted text to appear. Then, in command mode, type p to reinsert the text. If you are inserting a line or paragraph use the lower case p to insert the text on the line below the cursor or uppercase Pto place the text on the line above the cursor.

4.1.4.3. Copying Text

To duplicate text that exists in the file you are editing, use the yank and put commands to accomplish this function. Yank copies the selected text into a buffer and stores it there until another yank or deletion command occurs. Yank is often used in combination with a word or line object, for example:

After the desired text is yanked, place the cursor at the location where you wish to insert the text, then use the put command (p for pasting to the line below or P for pasting to the line above) to insert the contents of the buffer.

4.1.4.4. Replacing or Changing Characters, Words, or Lines

If you use the following commands to replace text, then you will be put temporarily into insert mode so that you can change a character, word, line, or paragraph of text.

4.1.4.5. Inserting Text

If you wish to insert text at any position in a line, first position the cursor to the right of where you wish the inserted text to appear. Then, type i to get vi into insert mode. Finally, enter the desired text (note that the text is inserted before the cursor). Press {Esc} to return to command mode.

4.1.4.6. Inserting a Blank Line

Sometimes you want to insert a blank line in a text file. To insert a blank line below the line where your cursor is currently located, depress the o key, then depress {Esc} to return to command mode. You can use O to insert a line above the line the cursor is located on.

4.1.4.7. Appending Text

The append command can be used to add text anywhere in the current file. Append (command code a) is similar to the insert command, except that append inserts text after the cursor rather than before. Append is typically used for adding text to the end of a line, by placing your cursor where you wish to append text and pressing a. When you are finished entering text, press {Esc} to return to command mode.

4.1.4.8. Joining Lines

Since vi does not have automatic word wrap, it is not unusual when editing lines to end up with lines that are too short. The appearance of these lines can be improved if they are joined together. Lines are joined by placing the cursor cursor on the first line to be joined and typing J. As with other commands, you can precede join with a number to join multiple lines (e.g., 4J joins 4 consecutive lines).

4.1.4.9. Undo

If you, make a mistake when editing, you can undo it immediately after the mistake is made. However, you must not move the cursor from the line where you made the change. Undo is implemented with one of the following commands:

4.1.5. Closing and Saving Files

When you edit a file in vi, you actually edit a copy of the file rather than editing the original file. The following sections describe commands to use when closing a file, quitting vi, or both.

4.1.5.1. Quitting and Saving a File

The command ZZ (in uppercase) allows you to quit vi and save the modified (edited) file, after which you are returned to the UNIX prompt. To quit and save, you can also use the following commands:

4.1.5.2. Quitting without Saving Changes

Occasionally an editor session does not yield the result that you want it to. In such cases, one might erase all edits made to the file and either start over or quit. The following two commands support this type of activity:

4.1.6. Advanced Command Usage

After learning some basic vi commands, one can expand one's skills by trying complex commands. Some commands are generally used in combination with a text object.

4.1.6.1. Combining Multiple Commands

A useful feature of vi is the ability to combine multiple low-level commands to produce a more powerful command.

Example. If you use the command dw to delete a word, that combines the delete (d) command with the word object.

If you want to delete multiple words, you can add a number to the command described above.

Example. If you want to delete 2 words you might use 2dw or d2w.

The general format for a vi command can be expressed as:

As in the second of the previous two examples, you can use:

Additional Exercise. Try some of the following combinations of commands and objects:

4.1.6.2. Repeating a Command

If you are doing repetitive editing, you may wish to repeat a command. The vi editor uses the dot (.) in command mode to repeat the last command you issued.

4.1.6.3. Simple Customization of vi

Several configuration options can be set from within vi. For example, newer versions allow you to set a right margin that will then force vi to automatically wrap lines of text as you type. This is accomplished through a variation of the :set command, which changes various options in vi.

Example. To wrap text lines of maximum length 60 characters, while command mode, type

to specify a right margin set at the 60-th column.

Another useful option is :set number, which causes vi to display line numbers in the current file. However, these numbers do not appear in the text that you save, so they do not interfere with the file contents.

To view a listing of other options, type :set all in command mode.

To view only those options which are currently in effect, type set: by itself.

Note that options you set while in a vi session will apply during that session only. To make permanent changes to your vi environment, you could edit your .exrc file (a hidden file in UNIX). Be careful, as you should not edit this file unless you know exactly what you are doing!

4.1.7. vi Command Summary

Cut/Paste Commands (CPCs): Extensions to CPCs: Cursor Relocation Commands (CRCs): Extensions to CRCs: Searching and Substitution Commands: Insert Mode: Exiting and Entering vi Complex Commands:

An excellent tutorial for the vi editor is found at University of Hawaii at Manoa's College of Engineering, by clicking on this vi Tutorial Link.

You can find all of the information you need to start using vi in this tutorial, and most of the information for advanced use in the UHM tutorial. Other links to UNIX vi pages can be found at the following URLs:

4.1.8. emacs Editor Tutorial

GNU Emacs is a complex text editor written by Richard Stallman. Emacs is more powerful than vi and is found on many UNIX and VAX VMS systems. Emacs is known for its window-based editing capabilities, for example, it is possible to edit a file in one window, compile a source program in another, and have another process execute in a third.

Unfortunately, the Emacs command syntax is not easy to learn. However, the command syntax can be customized by you to be whatever syntax you find easiest to use and remember.

Rather than present an overview of Emacs here, you are referred to the following Online Emacs Tutorial, which is already in hypertext form. On your CISE account, you should have a Netscape browser running in one window on your workstation, and emacs running in another window, so you can work along with the tutorial.

Other emacs tutorials of interest include:

If you use a tutorial to learn emacs, it is suggested that you run emacs in one workstation window, and the tutorial (on your Web browser) in another window. Also, emacs has a built-in tutorial that can be accessed by typing {Ctrl}-h t (that means holding the Ctrl and h keys down together, then releasing those keys, then typing a lower-case t).

4.2. Compilers: C, C++, Java

Reading Assignments and Exercises

A compiler translates the source code for a program, which you produce with a text editor like vi or emacs, into object code, which is then linked with libraries and run on a processor, as described in Sections 1 and 4.3 of these Web notes.

The three languages in common use for scientific and engineering programming are C, C++, and FORTRAN. Because FORTRAN is generally used for scientific programming, and because C and C++ are more modern languages, we will concentrate on the latter. Additionally, Java is of interest due to its application in Web-based programming.

It is beyond the scope of this Web page to provide a detailed tutorial for C, C++, or Java. Instead, after a brief discussion, you will be referred to a series of links to such tutorials on other Web sites.

4.2.1. C Programming Language

The C language was developed at AT&T Bell Laboratories in the early 1970s by Dennis Ritchie. At that time, operating systems and large software systems were typically coded in assembly language, for efficiency. Ritchie reasoned that a properly-designed high-level language could provide the user with access to system-level functions as well as programming language constructs such as arithmetic operations, control structures, and I/O. Thus, C was developed for designing and coding prototype systems.

During the past 25 years, C has evolved into a general-purpose language that has become widely available for workstations, parallel machines, and embedded processors. According to its design philosophy, C combines the convenience of high-level languages with the power and detail of assembly language. In 1989, the American National Standards Institute (ANSI) approved a standard version of the C language called ANSI-C. This version is now used in software engineering applications. A superset of the C language, called C++, is reviewed in Section 4.2.2 of these Web notes.

UNIX was originally written in C and is packaged with a standard C compiler. Most UNIX utilities are written in C, as are many commercial software products, such as The Motif graphical user interface, the X windows library, and the Oracle database system.

Several useful links to C language tutorials include:

  • On-line C tutorial -- A quickly read, easily understood tutorial that covers the central topics of C and helps the reader to understand more advanced tutorials.

  • C Tutorial - a good "first tutorial" about the C programming language, with example programs and explanations about various aspects of coding and working with the C language.

  • ANSI C for UNIX programmers is a 73 page book in PostScript format, which you can download. This book describes the differences between C and other programming languages that might be problematic for new programmers. This book also contains step-by-step explanations of the C language.

    If you do not have a PostScript viewing program, you can download the GhostScript viewer called gsview

  • C-LESSON.ZIP A ZIP-compressed file that contains a complete C tutorial, oriented toward UNIX users and programmers.

  • comp.lang.c Frequently Asked Questions, have answers to common questions about the C language - a good resource to consult when you're confused or don't know what to do in the presence of a mistake or "bug".

  • Newsgroup for C Users, also called comp.lang.c this group discusses many obscure issues of C programming. Best not to ask a question here until you have read the FAQ listed on-line or referenced in the preceding item.

  • As in the vi and emacs tutorials, you will want to have the tutorial running in your browser window while you use the C compiler in another window of your workstation's desktop workspace.

    4.2.2. C++ Programming Language

    The C++ programming language is a popular high-level programming language developed at AT&T Bell LAbs by Bjarne Stroustrup. C++ supports the development of object-oriented software, which facilitates the building of complex software systems using many techniques learned over decades of experience building large, complex physical systems such as airplanes and skyscrapers.

    Most programming languages have executable units, such as subroutines or functions. In C++ the executable unit is a function. Additionally, a file containing C++ code is called a translational unit. The ability to group C++ statements and functions into named units allows the programmer to design small, clear programs that perform small functions in a clear, understandable way. Then, one can organize a larger software system from the small programs, similar to building a book from its chapters, a chapter from its sections, a section from its subsections, and so forth. This facilitates the practice of code re-use, where various functions can be called from one or more libraries that are publically available. Thus, the work of programming can be reduced by using standard modules.

    Several useful C++ tutorials are listed, as follows:

  • GNA - Introduction to Object-Oriented Programming - explains concepts and practical aspects of object-oriented programming. C++ is the featured language. This is a must read item, prior to learning C++.

  • Neil's C++ Tutorial, is a "next step" in the learning of C++. This site explains the main features of C++ clearly and straightforwardly. A personal tone makes this tutorial easy to read.

  • Chris Bill's C++ Instructional Site - an excellent C++ tutorial that is is complete and moves the reader toward more advanced programming techniques. Some of the expressions use a color syntax-highlighting system so every item (keyword, identifier, or comment) has its own color. These makes the learning of C++ much easier.

  • C++ Tutorial - a more advanced C++ tutorial that should not be attempted until the first three links in this section are read. An excellent in-depth look at C++.

  • C++ tutorial for C users - compares C and C++, and is useful for people who know the C language. The primary differences between the two languages are explained, with examples.

  • As in the vi, emacs, and C tutorials, you will want to have the tutorial running in your browser window while you use the C++ compiler in another window of your workstation's desktop workspace.

    4.2.3. Java Programming Language

    Java is a programming language that is object-oriented as well as being a hybrid of a compiled and interpreted language. By compiled, we mean that you write Java source code, then translate it into Java bytecodes using a Java compiler. The bytecode, which is a form of intermediate code, is then run on a hardware- or machine-specific runtime module. Thus, the front end of Java (the language and compiler) is machine-independent, while the back end (runtime module) is machine-specific. This allows great portability of code, provided that the machine you want to run Java on has a Java runtime module.

    The Java programming language was develped for Web-based programming and object-oriented, portable software development. Java is similar in syntax to C++, but avoids many of the dangerous practices of C++. For example, all pointer manipulation in Java is done automatically and is transparent to the user. All array references are checked at runtime, and memory management is performed by the runtime module (program that runs the compiled Java code). Java employs the usual concepts of classes, objects, and inheritance involved in object-oriented programming. Java also has a rich class library that contains platform-independent support for event-driven programming and graphics-oriented programming. This makes Java more useful for graphical user interfaces.

    Recommended Java tutorials include:

  • Richard Baldwin's Java Tutorials - beginning, intermediate, and advanced Java tutorials developed by a CIS professor at Austin Community College for his students. Very practical, stepwise lessons that are easy to follow and understand. You might have to wait a minute or two for the Web page to resolve the correct reference to this tutorial, but the wait is worth it.

  • IBM Java Course - one of the better, in-depth Java tutorials

  • Introduction to JavaScript - Contains numerous Javascript examples along with source code and explanations. It also has links to other Javascript sites and a book store containing some good books on Javascript and other web related technologies.

  • Sun Microsystems Java Tutorial - the definitive Java source, from the inventors of the Java language.

  • More Sun Java Tutorial Information - A practical guide for programmers with hundreds of complete, working examples.

  • As in the vi, emacs, C, and C++ tutorials, you will want to have the tutorial running in your browser window while you use the Java compiler and runtime modules in other windows of your workstation's desktop workspace.

    4.3. Libraries, Linkers, and Runtime Modules

    Reading Assignments and Exercises

    4.3.1. Libraries

    A library is a collection of programs that can be accessed by other programs. This concept is analagous to a library of books or CDs, which might be assembled by one person or many people, but can be accessed by many other persons.

    In UNIX, there are two kinds of libraries: source code and object libraries. Source libraries are collections of files, where each file contains a small program. Using a text editor such as emacs, you can include a source file in your program source code. This is a simple but potentially cumbersome way of linking code together. Also, if the included function calls other functions that you don't know about, then you can have unresolved links in your code that do not make it compilable.

    Object libraries are collections of compiled programs that are linked to other programs. Control dependencies are resolved by a link editor such as the UNIX ld utility, discussed in Section 4.3.2. As a result, object libraries tend to be a more reliable approach to code re-use than source libraries.

    Library calls are a standard procedural practice in UNIX. When you perform the man command, you often see collections of libraries such as the following:

    libadm          libadm (4)      - general administrative library
    libaio          libaio (4)      - the asynchronous I/O library
    libbsm          libbsm (4)      - basic security library
    libc            libc (4)        - the C library
    libcfgadm       libcfgadm (4)   - library of configuration adminstration 
                                         interfaces 
    libci           libci (4)       - Sun Solstice Enterprise Agent Component 
                                         Interface Library
    libdevid        libdevid (4)    - device id library
    libdl           libdl (4)       - the dynamic linking interface library
    libdmi          libdmi (4)      - Sun Solstice Enterprise Agent DMI Library
    libdmimi        libdmimi (4)    - Sun Solstice Enterprise Agent Management 
                                         Interface Library
    libelf          libelf (4)      - ELF access library
    libintl         libintl (4)     - internationalization library
    libkrb          libkrb (4)      - Kerberos library
    libkstat        libkstat (4)    - kernel statistics library
    libkvm          libkvm (4)      - Kernel Virtual Memory access library
    libmp           libmp (4)       - multiple precision library
    libnisdb        libnisdb (4)    - NIS+ Database access library
    libnsl          libnsl (4)      - the network services library
    libpam          libpam (4)      - interface library for PAM (Pluggable 
                                         Authentication Module)
    libposix4       libposix4 (4)   - POSIX.1b Realtime Extensions library
    libpthread      libpthread (4)  - POSIX threads library
    librac          librac (4)      - remote asynchronous calls library
    libresolv       libresolv (4)   - resolver library
    librpcsoc       librpcsoc (4)   - obsolete RPC library
    librpcsvc       librpcsvc (4)   - miscellaneous RPC services library
    libsec          libsec (4)      - File Access Control List library
    libsocket       libsocket (4)   - the sockets library
    libssagent      libssagent (4)  - Sun Solstice Enterprise Agent Library
    libssasnmp      libssasnmp (4)  - Sun Solstice Enterprise SNMP Library
    libsys          libsys (4)      - the system library
    libthread       libthread (4)   - the threads library
    libtnfctl       libtnfctl (3x)  - library for TNF probe control in a 
                                         process or the kernel
    libtnfctl       libtnfctl (4)   - library of TNF probe control routines 
                                         for use by processes and the kernel
    libucb          libucb (4)      - the UCB compatibility library
    libvolmgt       libvolmgt (4)   - volume management library
    libw            libw (4)        - the wide character library
    libxfn          libxfn (4)      - the XFN interface library
    libxnet         libxnet (4)     - X/Open Networking Interfaces library
    

    and so forth, which are from the Sun OS man pages. This rich variety of libraries enables users to access a wide variety of functions that would otherwise have to be written prior to software design. We next discuss the ld command, with which libraries are constructed.

    4.3.2. Linking Object Files

    In software engineering practice, it is desireable to have reusable code and modular structure. Thus, it is practical to write source code in small functions, with one function per file. After compiling the functions, then we need to construct a larger object file from the compiled programs. That is, after you have compiled a collection of small C programs that constitute a source library, you should collect them into one object file. This process is called link editing, and is accomplished with the UNIX ld command.

    The UNIX ld command combines relocatable object files, performs relocation, and resolves external symbols. The ld command operates in two modes: static or dynamic, depending on whether or not the -d option is specified.

    In static mode ( -dn option), relocatable object files whose filenames are specified as arguments to ld are combined to produce an executable object file (machine code). If the -r option is specified, relocatable object files are combined to produce one relocatable object file.

    In dynamic mode ( -dn option), which is the default mode, relocatable object files whose filenames are specified as arguments to the ld command are combined to produce an executable object file that are linked at execution with any shared object files whose filenames are also specified as arguments to the ld command. If the -G option is specified, relocatable object files are combined to produce a shared object. In all cases, the output of ld is written to the executable file a.out by default.

    If any argument to the ld command references a library, then ld searches the library exactly once at the point it encounters the library in the argument list. The library may be either a relocatable archive or a shared object. For an archive library, ld loads only those routines that define an unresolved external reference. Also, ld searches the archive library symbol table sequentially with as many passes as are necessary to resolve external references that can be satisfied by library members. For a detailed explanation of this procedure, use the command man ar. Thus, the order of members in the library specification is functionally unimportant, unless multiple library members exist that define the same external symbol.

    A shared object consists of an indivisible, whole unit, that has been generated by a previous link-edit of one or more input files. When the link-editor processes a shared object, the entire contents of the shared object become a logical part of the resulting output file image. The shared object is not physically copied during the link-edit as its actual inclusion is deferred until process execution. This logical inclusion means that all symbol entries defined in the shared object are made available to the link-editing process.

    Example. Suppose you have three programs prog1.c, prog2.c, and prog3.c that you wish to compile and link to form one object module called progP.c. The following steps are performed:

    Step 1. Compile the source files separately using the C compiler (called cc in UNIX):

      cc -c prog1.c
      cc -c prog2.c
      cc -c prog3.c

    This produces three object files, automatically named by the C compiler as prog1.o, prog2.o, and prog3.o.

    Step 2. Manually link the separate object files using the ld command, as follows:

      ld -n /lib/crto.o prog1.o prog2.o prog3.o -lc -o progP

    which will (a) link the standard C runtime module (crt0.o), (b) link the object files as shown, (c) specify the standard C library /lib/libc.a, and (d) produce an object file propgP.o.

    The standard C library is linked because ld, when it encounters an -lx option, searches the directories /lib, /usr/lib, and /usr/local/lib for the library /lib/libx.a.

    An alternative to using the ld command is to use the C compiler's linking capabilities. In the previous example, one would use the compiler to link object files, as follows:

    Another way to link files is to use a makefile, as described in Section 4.4. This is a "master control" file for compilation and linking that allows you to specify the structure of large software systems clearly, in a manner that can be easily maintained.

    4.3.3. Runtime Operations

    Dynamic applications consist of one or more dynamic objects, which can change structure or functionality with time. These objects typically include a dynamic executable together with its shared object dependencies (i.e., objects that are used by the executable). In the initialization and execution of a dynamic application, an interpreter completes the binding of the application to its shared object dependencies. For example, in the Sun Microsystems SolarisTM operating system, the interpreter is called the runtime linker.

    During the link-editing of a dynamic executable, a special-purpose .interp section, together with an associated program header (a file that provides information to a program about its inputs, outputs, and compilation/execution environment), is created. The pathname to the program's interpreter, which is contained in the .interp section, can be specified when the executable is being constructed by the -I option to ld. The default name supplied by the link-editor is that of the runtime linker, which is located at /usr/lib/ld.so.1.

    During the process of executing a dynamic executable the OS kernel maps the file and locates the required interpreter. The utilities exec and mmap are employed in this location function. The kernel then transfers control to the interpreter, passing sufficient information to the interpreter to allow the interpreter to continue binding the application prior to running it.

    In addition to initializing an application, the runtime linker provides several services, which allow the application to extend its address space by mapping additional shared objects and binding to symbols within them.

    In particular, the runtime linker can:

  • Analyze the application's dynamic information section (in a file called .dynamic and determine the required shared object dependencies (called SODs, for brevity).

  • Locate and map the relevant SODs, then analyze their dynamic information sections to find out what additional SODs are required to run the program.

  • After the SODs are located and mapped, the runtime linker performs necessary relocations that bind shared objects prior to process execution.

  • Call initialization functions provided by the SODs. By default, these functions are called in an order that is the reverse order of the topologically sorted dependencies. If cyclic dependencies exist, then the initialization functions are called in the sorted order with each cycle removed. The command ldd can display the initialization order of shared object dependencies.

  • Pass control to the application.

  • Occasionally, a function must be bound during execution. This practice, called late binding, can be performed by the runtime linker.

  • Call any finalization functions when shared objects are deleted from an executing process. These finalization functions are usually called in order of the topologically sorted dependencies.

  • Possibly be used by the application to acquire additional shared objects via the dlopen call. Similarly the application can bind to symbols within these objects using the dlsym call.

  • Note also that the runtime linker uses a prespecified search path to locate the dynamic dependencies of an object. The default search paths are the runpath recorded in the object, and then /usr/lib. The runpath is specified when the dynamic object is constructed using the -R option to ld. The environment variable LD_LIBRARY_PATH can also be used to indicate directories to be searched by the runtime linker before it searches the aforementioned default directories.

    4.4. Overview of Makefiles

    Reading Assignments and Exercises

    The make command invokes a powerful UNIX program that makes or assembles programs from source codes and libraries. Fortunately,, make is easy to use and has some "intelligent" features. For example, the make utility compares the date/time-last-modified of the source code files required by your program. If a source file has been modified since its corresponding object file was last created (recall that object code is created from source code by compilation), then make will automatically recompile the modified source files.

    The make utility reads the file makefile or Makefile in the current directory to find the rules for making a program.

    Example.A simple makefile looks like this:

    The first line of this example is a comment, and thus starts with (#). The next line states that the target program that we want to make, namely science, depends on the source file science.c. If the file science.c has been modified since the target science was last created, then science will be rebuilt by executing the commands on the following lines.

    Important Note: The command lines must be indented with a tab character, shown as TAB in this example.

    In the next example, the single command line says to recompile the program using cc, the UNIX C compiler.

    Example. To make the program science, issue the command make with a target name, as follows:

    In the preceding example, the program only involved compilation of one source file. The make utility is especially useful when a program is compiled from many source files.

    Example. The following instance of the program science uses two files, namely, science.c and graph.c, which are expressed as (compiled) object files.

    This instance of the makefile states that the program science depends on two object files, science.o and graph.o. Since no statement specifies compilation of the object files, the make utility uses its built-in rules. In particular, make will assume there are appropriately named C or Fortran source files code in the current directory, and will compile the code (if found) to yield object files. Since the C compiler is specified, make will look for science.c and graph.c.

    Since science depends on the object files, make will check to see if these files are current (i.e., compiled after the last modification to the source file) before making science. Since, the file science.o implicitly depends on science.c, and make will check the modification time of science.c. If it has changed since science.o was created, make will recompile the object file. It will then do the same for graph.o.

    After compilation, make will check the modification times of the object files and compare them to the target science. If either object file has been modified, then make will run the command line which recompiles (links) science. A sample UNIX session follows:

    % make kabs                               Command issued from working directory.   
        f77 -c kabs.f                        Build kabs.o object file.   
        f77 -O -o kabs kabs.o graf.o       Then build the target.   
    

    Thus, the steps involved in executing make depend on the state of the source.

    Makefiles can be used to build arbitrarily complex programs. Some examples are given in your text. Since this course is not concerned with C programming primarily, the following links to make tutorials are suggested reading if you want to follow up and learn more about makefiles:

    C language textbooks are also good references for learning to program with makefiles.


    This concludes our overview of basic UNIX compilation and linking commands. We next discuss the software development process with a UNIX operating system.


    References