Sunday, February 8, 2009

MCA 301

What is an Operating System?
An operating system is an important part of a computer system. You can view a computer system as being built from three general components: the hardware, the operating system, and the applications. (See Figure 1.1.) The hardware includes pieces such as a central processing unit (CPU), a keyboard, a hard drive, and a printer. You can think of these as the parts you are able to touch physically. Applications are why you use computers; they use the rest of the system to perform the desired task (for example, play a game, edit a memo, send electronic mail). The operating system is the component that on one side manages and controls the hardware and on the other manages the applications.
Figure 1.1. Computer system components.
When you purchase a computer system, you must have at least hardware and an operating system. The hardware you purchase is able to use (or run) one or more different operating systems. You can purchase a bundled computer package, which includes the hardware, the operating system, and possibly one or more applications. The operating system is necessary in order to manage the hardware and the applications.
When you turn on your computer, the operating system performs a series of tasks, presented in chronological order in the next few sections.
Hardware Management, Part 1
One of the first things you do, after successfully plugging together a plethora of cables and components, is turn on your computer. The operating system takes care of all the starting functions that must occur to get your computer to a usable state. Various pieces of hardware need to be initialized. After the start-up procedure is complete, the operating system awaits further instructions. If you shut down the computer, the operating system also has a procedure that makes sure all the hardware is shut down correctly. Before turning your computer off again, you might want to do something useful, which means that one or more applications are executed. Most boot ROMs do some hardware initialization but not much. Initialization of I/O devices is part of the LINUX kernel.
Process Management
After the operating system completes hardware initialization, you can execute an application. This executing application is called a process. It is the operating system's job to manage execution of the application. When you execute a program, the operating system creates a new process. Many processes can exist simultaneously, but only one process can actually be executing on a CPU at one time. The operating system switches between your processes so quickly that it can appear that the processes are executing simultaneously. This concept is referred to as time-sharing or multitasking.
When you exit your program (or it finishes executing), the process terminates, and the operating system manages the termination by reclaiming any resources that were being used.
Most applications perform some tasks between the time that the process is created and the time that it terminates. To perform these tasks, the program makes requests to the operating system and the operating system responds to the requests and allocates necessary resources to the program. When an executing process needs to use some hardware, the operating system provides access for the process.
Hardware Management, Part 2
To perform its task, a process may need to access hardware resources. The process may need to read or write to a file, send data to a network card (to communicate with another computer), or send data to a printer. The operating system provides such services for the process. This is referred to as resource allocation. A piece of hardware is a resource, and the operating system allocates available resources to the different processes that are running.
See Table 1.1 for a summary of different actions and what the operating system (OS) does to manage them.


Table 1.1. Operating system functions.
Action


OS Does This


You turn on the computer
Hardware management
You execute an application
Process management
Application reads a tape
Hardware management
Application waits for data
Process management
Process waits while other process runs
Process management
Process displays data on screen
Hardware management
Process writes data to tape
Hardware management
You quit, the process terminates
Process management
You turn off the computer
Hardware management
From the time you turn on your computer until you turn it off, the operating system is coordinating the operations. As hardware is initialized, accessed, or shut down, the operating system manages these resources. As applications execute, request, and receive resources, or terminate, the operating system takes care of these actions. Without an operating system, no application can run and your computer is just an expensive paperweight.
Linux's History

Linux was developed as a freely distributable version of UNIX. UNIX is the most widely used operating system in the world and has long been the standard for high-performance workstations and larger servers. UNIX, first developed in 1969, has a strong programmer-oriented user group that supports the operating system.
How did UNIX get its name? It was based on operating systems called MULTICS (MULTiplexed Information and Computing System). Ken Thompson, Dennis Ritchie, and Brian Kernighan were involved the design of a new operating system based on MULTICS that would be much simpler. They called the new operating system UNICS (Uniplexed Information and Computing System), which was quickly changed to UNIX.
Because UNIX is a commercial product, it must be bought for each platform it runs on. Licensing fees for UNIX versions for PC machines range from a few hundred dollars to several thousand. In an attempt to make UNIX widely available for no cost to those who want to experiment with it, a number of public domain UNIX systems have been developed over the years.
One of the early UNIX workalikes was Minix, written by Andy Tanenbaum. Although Minix didn't have a full range of features, it provided a small operating system that could be used on PC machines. To expand on Minix, a number of users started developing an enhanced operating system that would take advantage of the 80386 CPU's architecture. One of the primary developers of this system, which became known as Linux, was Linus Torvalds of the University of Helsinki. He released an early version of Linux in 1991. A first commercial, almost bug-free release was unleashed to the programming community in March 1992.
Soon, many programmers were working on Linux, and as the challenge and excitement of producing a growing UNIX workalike caught on, Linux grew at a remarkable rate. As the number of developers working on Linux grew, the entire UNIX workalike operating system was eventually completed and now includes all the tools you will find in a commercial UNIX product. Linux continues to grow as programmers adapt features and programs that were originally written as commercial UNIX products to Linux. New versions of Linux and its utilities are appearing at an astounding rate. New releases often appear weekly.
To avoid any charges for Linux, the Linux developers do not use any code from other UNIX systems. There are no licensing fees involved with the Linux operating system, and part of its mandate is to be freely available. Some companies have undertaken the task of assembling and testing versions of Linux, which they package on a CD-ROM for a (usually) minimal price.
Linux is not based on a single version of UNIX; it is a consolidation of the best features of BSD UNIX and System V. BSD UNIX was developed at the University of California at Berkeley, starting in 1977. Several major releases increased the power of BSD UNIX. Several standard UNIX programs originated at BSD, although BSD stopped its UNIX development in the early 1990s. AT&T, which developed the first version of UNIX, continued their UNIX development by producing a series of UNIX versions called System III, System IV, and System V. Linux uses the last primary release of BSD UNIX called 4.4BSD as its base and takes some other features from the latest release of System V, called System V Release 4 (SVR4).












Linux’s relationship to Unix
Several versions of UNIX and UNIX-like systems have been made that are free or extremely cheap and include source code. These versions have become particularly attractive to the modern-day hobbyist, who can now run a UNIX system at home for little investment and with great opportunity to experiment with the operating system or make changes to suit his or her needs.
An early UNIX-like system was MINIX, by Andrew Tanenbaum. His books Operating Systems: Design and Implementations describes MINIX and includes a source listing of the original version of MINIX. The latest version of MINIX is available from the publisher. MINIX is available in binary form for several machines (PC, Amiga, Atari, Macintosh, and SPARCStation).
In addition to the BSD386 product from BSDI, there is a free version of UNIX also based on the BSD releases, and called, confusingly, 386BSD. This is an effort by Bill and Lynne Jolitz to create a system for operating system research and experimentation. The source is freely available, and 386BSD has been described in a series of articles in Dr. Dobbs' Journal.
Another popular source version of UNIX is Linux. Linux was designed from the ground up by Linus Torvalds to be a free replacement for UNIX, and it aims for POSIX compliance. There are current efforts to make Linux reliably run both SVR3.2 and SVR4 binaries. There is also a project called WINE to create Microsoft Windows emulation capability for Linux.

Linux distributions
Several versions of Linux are available, depending on which CD-ROM or FTP site you visit. This book doesn't care which version you use, because it applies to practically every version written. As of this writing, the latest Linux kernel versions were 1.2.13 and 1.3.15. The CD-ROM included with this book provides Slackware release 2.3, which includes the kernel version 1.2.8 (the last really stable version the author tested). You can change kernel versions by obtaining the source code for a new release, compiling it, and replacing your existing kernel. This procedure is covered in more detail later in the book.
You may find several CD-ROM distributions available at your local reseller. InfoMagic's Slackware release, for example, comes on four CD-ROMs and bears the name Linux Developer's Resource. In addition to the complete Linux system, it includes source code, FTP archives, full documentation, several extension products, and demonstration software of commercial applications (including WordPerfect). Some of this material is included on the CD-ROM at the back of this book.

Linux architecture
















Installing and Updating Linux

You probably already have installed Linux. Even so, you may not be happy with the installation, either because of poor organization or because you were experimenting with it and would like to try again with a better configuration. This chapter discusses the issues you should address when you install Linux for the first time (or reinstall it, as the case may be) and how to update your existing Linux installation with new software releases.
The process for installing Linux is straightforward, although lots of little potential problems are scattered throughout the process. Don't believe the easy installation claims on many packages of the distribution software! Several steps require patience, experimentation, and a knowledge of what is going on before Linux will install painlessly. The essential steps for installing Linux are as follows:
Create boot and root disks for Linux.
Partition the hard disk.
Boot Linux from a floppy disk.
Create a swap file partition.
Create a Linux filesystem.
Install the Linux software.
Configure the kernel.
Set the boot process.
Reboot into Linux from your hard disk.
This chapter covers each of these steps in more detail. The process is very similar for installing from a CD-ROM and from a floppy disk (which may have come from an FTP site, for example). Because CD-ROM is the most common form of installation, this chapter uses that process as an example.
If you are installing from floppy disks and have downloaded the distribution files (or copied them from a CD-ROM), you will need a DOS-formatted floppy disk for each file in the distribution disk set. You can use standard DOS COPY commands to copy the disk set files to the floppy disks, using one floppy for each file in the distribution set. The files are all numbered so you know which floppy disk is in which set, and what their order should be.

Creating Boot and Root Disks

Even if you are installing from CD-ROM, you need two high-capacity floppy disks (either 1.2M or 1.44M). These disks are the boot and root floppy disks. The boot floppy disk holds the kernel that is used to start Linux the first time, leading to your installation. The root floppy disk holds a small filesystem that includes utilities needed for the installation. The two disks together form a complete and very small implementation of Linux. Enough of a system is on the two floppy disks to play with Linux, although many of the utilities are missing.
In most cases, the boot and root floppy disks are copied from existing files called images. The image is a precompiled version of the system that you duplicate on the floppy disks, eliminating the need to start from scratch. CD-ROM and FTP distributions have directories for several boot and root images, depending on the hardware on your system. You must select the images that match your hardware as much as possible, copy them to the floppy disks, and start your system with the floppy disks. You can do most of these steps from DOS, although you can't use the DOS COPY command to create the boot and root floppy disks. You must create the floppy disks with a utility that ignores the DOS formatting. This utility, commonly called RAWRITE.EXE, is included with most Linux software distributions.
Selecting a Boot Kernel and Root Image

CD-ROMs usually have directories under the root directory called bootdsks.144 and rootdsks.144 (for 3.5-inch 1.44M floppy disks) and bootdsks.12 and rootdsks.12 (for 5.25-inch 1.2M floppy disks), which contain the boot and root images, respectively. To find these directories, run DOS either from a floppy disk or a partition on your hard disk to examine the CD-ROM. The boot and root directories for 1.44M floppy disks from a typical CD-ROM Linux distribution are shown in Figure 3.1. If you are copying your files from an FTP site, you can select the boot and root images you need while connected to the remote FTP machine and transfer only the images you need to your local machine.
Figure 3.1 The boot and root directory entries for 1.44M floppy disk images, which are used to create the boot and root floppy disks needed to install Linux.
The types of boot kernels usually available are described in a file in the kernel image directories (usually called README, READ.ME, or WHICH.ONE). The boot kernel images are named to reflect the hardware for which they have drivers installed into the kernel. For example, the scsi kernel image has drivers in the kernel for SCSI-based systems; if you are on a PC that has a SCSI controller, hard disk, and CD-ROM, this is the image you want to copy to your boot floppy disk. The number of boot images available is quite large. These are the primary images available from most CD-ROMs and FTP sites and the hardware they are designed to handle:
aztech
IDE and SCSI hard disk drivers, and Aztech non-IDE CD-ROM support, including Aztech, Okana, Orchid, and Wearnes non-IDE CD-ROM drives
bare
IDE hard disk drivers only (no CD-ROM support)
cdu31a
IDE and SCSI hard disk drivers, with a Sony CDU31 or Sony CDU33a CD-ROM drive
cdu535
IDE and SCSI hard disk drivers, with a Sony 535 or Sony 531 CD-ROM drive
idecd
IDE and SCSI hard disk drivers, with IDE or ATAPI CD-ROM drive
mitsumi
IDE and SCSI hard disk drivers, with a Mitsumi CD-ROM drive
net
IDE hard disk drivers and Ethernet network card drivers
sbpcd
IDE and SCSI hard disk drivers with Sound Blaster Pro or Panasonic CD-ROM drivers. This image is for CD-ROM drives run off a Sound Blaster card (as supplied in many Sound Blaster multimedia kits).
scsi
IDE and SCSI hard drivers with SCSI peripherals (CD-ROM drives)
scsinet1
IDE and SCSI hard disk drivers, SCSI CD-ROM driver, and Ethernet drivers for networking. The SCSI drivers support Adaptec 152X, 1542, 1740, 274x, and 284x adapters, Buslogic adapters, EATA-DMA adapters (such as DPT, NEC, and AT&T cards), Seagate ST-02 adapters, and Future Domain TCC-8xx and 16xx adapters. SCSI adapters compatible with any of these cards will also work.
scsinet2
IDE and SCSI hard disk drivers, SCSI CD-ROM driver, and Ethernet drivers for networking. The SCSI drivers support NCR5380-based adapters, NCR 53C7 and 8xx adapters, Always IN2000 adapter, Pro Audio Spectrum 16 adapter, Qlogic adapter, Trantor T128, T128F, and T228 adapters, Ultrastor adapters, and the 7000 FASST adapters. Compatibles of any of these cards should also work.
xt
IDE and IBM PC-XT-compatible hard disk drivers
With some distributions, an extension is added to the kernel image name to indicate the floppy disk type. For example, if the kernel image is for a 1.44M floppy disk, it will have the filetype .144 as part of the name. Similarly, a filetype of .12 indicates a 1.2M image. You cannot interchange these images, or the diskette will be useless (in other words you cannot load a .12 image onto a 1.44M diskette). Most distributions don't bother with this convention, since the files are in the appropriate directories for the floppy disk size.
You have fewer choices for the root floppy image. Most distributions include four basic images, although a few more esoteric images also appear from time to time. Each of the root images has the disk size as part of its name (color144 and color12, for example). The basic root floppy images are the following:
The color image offers a full-screen color-based installation script for installing Linux.
The tape image is designed to support Linux installation from a cartridge tape. This kernel has limited functionality and depends on the type of tape drive used. Typically, QIC drives are supported, but users of some models have reported problems.
The tty image is a dumb terminal installation version with no color or graphics.
The umsdos image is used to install UMSDOS, which allows you to install Linux into an existing MS-DOS partition. The installation script creates the subdirectories it needs. UMSDOS is not as efficient or fast as a dedicated Linux partition, but you can retain your current disk partitions.
The color root image is a lot more attractive than the tty image and can make the Linux installation a bit friendlier. The color image is intolerant of typing errors and doesn't always proceed smoothly, however. It's worth a try, in most cases, unless you know exactly how you want to install Linux. The color process tends to require much more user interaction, including clicking OK buttons at many stages.
Once you have determined which of the boot and root images you will use (if you are not sure, pick the boot image that most closely matches your hardware configuration and the color or tty root image), you can create the boot and root floppy disks. If you choose the boot and root images incorrectly, don't worry. All that will happen is that you won't be able to install Linux, and you'll have to start the process again.
Creating the Boot and Root Floppy Disks

You can create the boot and root floppy disks either from DOS or from UNIX (or Linux). If you don't run DOS yet, and don't have a DOS boot disk, you will have to use another machine to create the two floppy disks. Because creating the floppy disk from DOS is the most common method, this section deals with this method first.
To create the boot and root floppy disks, you must use a utility program to write the image to floppy disk. If you obtained your boot and root images from an FTP or BBS site, the files may be compressed and archived. If they are, they will end with the filetype .gz. Before you can install the images to a floppy disk, you must decompress them with the gzip utility. If you are working from CD-ROM, you will have to copy the files to a DOS hard disk because you can't write the decompressed image to the CD-ROM. Even if you start with decompressed files, it may be easier to copy the images to a temporary DOS directory as it will save you the hassle of worrying about directory pathnames.
To decompress a .gz file, issue the command

gzip -d
where filename is the name of the compressed file (including the .gz extension). The -d option tells gzip to decompress the file. After the file is decompressed, the .gz file is erased and only the decompressed file remains (with the same filename, without the .gz extension). To decompress the scsi.144 and color144 images, for example, you would issue the following commands:

gzip -d scsi.gz

gzip -d color144.gz
To write the images to the two floppy disks you need two high-density floppy disks and the RAWRITE utility. The two floppy disks don't have to be blank, as the RAWRITE utility doesn't respect DOS file formats (although the disk must be formatted). The two floppy disks must be high density, though. You can mix disk types (in other words, you can use a 1.2M boot floppy disk and 1.44M root floppy disk) with some distributions of Linux, although it's not recommended for most systems. Keeping everything the same disk size is a lot easier. The disks must be formatted using DOS' FORMAT program. The boot floppy disk must be the correct size for your system's boot floppy disk drive (A: in DOS terms).
RAWRITE is a DOS program that writes the images, block-by-block, to the floppy disk. To use the RAWRITE program, just enter its name. RAWRITE prompts you for the name of the file to copy, and the destination drive letter. RAWRITE will then copy the images. Once the process is completed, DOS cannot read the floppy disk. Label the disks as the boot and root floppy disks, for convenience.
If you have access to a UNIX or Linux system, you can create the boot disks from within that operating system. You will need to put the two image files on the UNIX or Linux system, and use the dd utility to copy them to the floppy disks. This is also the procedure to follow if you are upgrading your existing Linux system to a newer release. First, make sure the images are decompressed (no .gz extension). If they are not, decompress them with the UNIX gunzip utility (a GNU utility that you may have to obtain from another source, if it's not included with your distribution). To decompress files in UNIX or Linux, issue the command

gunzip
where filename is the name of the image file with a .gz extension. The gunzip utility erases the compressed file and leaves an decompressed version in its place.
To copy the images to a floppy disk, you need to know the device name of the floppy drive within the operating system. For most systems, the first floppy drive is /dev/fd0, and the second floppy drive is /dev/fd1. (Some systems treat the floppy drives as raw devices, which have the names /dev/rfd0 and /dev/rfd1.) Copy the image files to the floppy disks with the command

dd if= of=/dev/fd0 obs=18k
where filename is the name of the decompressed image. The dd command converts file formats. The if and of parts of the command indicate the input and output filenames of devices. The obs portion of the command indicates the output block size (in this case, 18K).
For example, to copy the scsi and color144 images to the first floppy drive (3.5-inch 1.44M), issue the following two commands:

dd if=scsi of=/dev/fd0 obs=18k

dd if=color144 of=/dev/fd0 obs=18k
Linux is particularly stubborn about telling you your progress, so you won't see many messages. When dd starts the copy, it tells you how many blocks it will move. When it finishes, it returns the shell prompt to you without any message (unless the procedure failed). Figure 3.2 shows the command for copying the root kernel scsi to a floppy disk. After you copy both the root and boot kernels, you have completed this stage of the installation. The two floppy disks are now ready to boot a minimum Linux system for you.
Figure 3.2. You can use the dd command to copy the boot and root images to floppy disk from any Linux or UNIX system.
Partitioning the Hard Disk

Hard disks are divided into partitions, which are areas dedicated to an operating system. A hard disk can have up to four primary partitions, with some partitions being divided into more logical drives by the operating system software. A more complete discussion of partitions is in Chapter 4, "LILO."
If you are running Linux from a DOS partition using the UMSDOS root image, you don't have to worry about repartitioning your drives. Your existing drive's partitions will be used. However, because UMSDOS is a poor filesystem compared to Linux's, you will probably want to create your own Linux partitions. Check the later section "Using UMSDOS" for information on setting up UMSDOS.
Linux prefers two partitions: one for the Linux swap space and one for the Linux software filesystem itself. The swap space is used as an extension of your machine's physical RAM and can be quite small. Technically, you don't need a swap partition, especially if you have lots of RAM, but it is a very good idea to create one anyway as your system can grind to a halt suddenly if RAM is exhausted. The Linux filesystem partition tends to be quite large, as it must hold all the Linux software. You can have several Linux filesystem partitions to hold utilities, applications, and user files, although one partition must be designated as the boot partition (where the kernel and primary utilities are located).
If you are using a hard disk that has an operating system already installed on it, you will have to repartition your hard disk to make room for Linux. This process will destroy anything already on your hard disk, so make backups of any existing data you want to keep!
You use the fdisk utility to partition a hard disk. The Linux version of fdisk does the same task as FDISK in DOS, although the menus are completely different (and much more complicated). Many PC-based UNIX systems also use fdisk to partition hard drives.
A DOS utility called FIPS sometimes allows non-destructive changes to your partitions, assuming no data is on the areas that will be repartitioned. FIPS is available from many sources, including most of the Linux FTP sites and on some Linux CD-ROMs. However, you should make backups, just in case.
You must decide how much space to allocate to the different partitions before you start, as changing your mind later will mean destroying all the data you have saved to disk. The Linux swap space partition size depends on the amount of RAM in your system, the number of users you expect, and the type of development you will do.
If you are going to maintain a DOS partition on the same disk, you will have to balance the disk space requirements of both operating systems against your total disk capacity. A minimum Linux filesystem partition will be about 20M, although closer to 100M is needed for a full X-based installation.
Determining the Size of the Linux Swap Space Partition

How big should the swap space partition be? No single number works for all installations, unfortunately. Generally, because the swap space is used as an extension of physical RAM, the more RAM you have, the less swap space is required. Add the amount of swap space and the amount of RAM together to get the amount of RAM Linux will use. For example, if you have 8M of RAM on your machine's motherboard and a 16M swap space partition, Linux will behave as though you had 24M RAM.
Linux uses the swap space by moving pages of physical RAM to the swap space when it doesn't need them, and moving them back again when it needs the memory pages. Why not make a very large swap space and let Linux think it's in heaven? The swap space is much slower in access time than RAM, and there is a point at which the size of the swap space starts to act against your Linux system's efficiency instead of for it. In addition, most versions of Linux have an upper limit of 16M for each swap partition. Those versions of Linux will, however, let you partition more than 16M to a swap space, but it will only use the first 16M. If needed, though, you can create multiple swap partitions. Up to eight swap partitions can exist, each up to 16M in size. The latest versions of Linux allow swap partitions larger than 16M, but it is wise to keep that size as a guide.
You may not even need swap space if you have lots of RAM. For example, if you have 16M of physical RAM and don't intend to do any application development or run X, you probably won't make much use of the swap space because Linux can fit everything it needs in the 16M. (You still should have a small swap space, just in case.) If you are running X, developing applications, or running memory-hog applications like databases, swap space is crucial even if you have lots of physical RAM. Even 16M RAM is not enough for X, so you need swap space.
A good rule is to create a swap space with the maximum size limit of 16M. Unless you have a very small capacity hard disk, a swap space of this size won't be a major drain on your resources, and it gives Linux plenty of space with which to work. If you don't want to allocate this much space, a good rule is to have a total of 16M RAM (swap space plus physical RAM). Don't eliminate the swap space completely, though, even if you have a lot of RAM. At a minimum, set up a 4M swap space. Running out of RAM can cause Linux to lock up or crash.
Once a swap space partition has been created, it is just like any other partition on the hard drive. If you want to change its size, you have to remove the existing partition and create a new one, although the space must be contiguous on the hard drive (which can be difficult to do if you have used all the space the drive offers for other partitions).
Setting up Partitions

You use the fdisk utility to set up the partitions on your hard disk. Remember that fdisk will destroy existing data on your disk! You can set up your Linux disk partitions either from DOS, or from within Linux. It really doesn't matter which approach you use, although the DOS FDISK program is a little easier to use than Linux's. If you are using DOS FDISK to repartition a DOS area on your drives, use it to set up the Linux swap space and filesystem partitions, too.
To set up partitions for Linux, remove any existing partitions first (unless you want to keep them as they are). If you intend to use DOS on the same system as Linux, DOS should be the first partition on the disk so it can boot. (You can use LILO to get by this restriction, but it is still a good rule to leave DOS as the first partition.) If you are keeping an existing DOS partition on your hard drive, leave the first partition as DOS if you can.
Create a DOS boot disk that can reformat and transfer the DOS kernel to the hard drive, regardless of whether you are leaving an existing DOS partition or creating a new one. To create the boot disk, use the DOS

format a: /s
command (assuming A: is the drive the disk is in). The /s option transfers the operating system kernel. Next, copy the utilities FDISK, FORMAT, SYS, and CHKDSK to the boot disk. You should also copy an editor such as EDIT(which requires the QBASIC files as well), and your existing CONFIG.SYS and AUTOEXEC.BAT files (although you could rename them). This disk will let you format any new DOS partitions. Alternatively, if you are starting from scratch with a new DOS partition, you can reload DOS from the original floppy disks when ready to format the DOS partition.
If you are removing an existing DOS partition and recreating a smaller one (as you would if your entire disk was DOS before Linux came into your life), follow these steps (after making a backup of your DOS data):
Remove the existing DOS partition.
Create a new primary DOS partition as the first partition.
Make the DOS partition active.
Reboot the system from your boot disk (or DOS disks).
Format the DOS partition and transfer the DOS kernel (COMMAND.COM).
Restore your backup files to the DOS partition. (You can do this step at anytime).
Next, set up the Linux swap space partition by creating a partition of the proper size. You can do this step either from DOS or when you have booted Linux from the boot and root floppy disks. The rest of this section assumes that you are setting up the partitions from DOS, although the process is the same either way.
Most versions of FDISK allow you to enter the size of the partition in megabytes, with the utility calculating the sector numbers that apply to it. Set the size of the Linux swap space to whatever size you decided, up to a maximum of 16M. Don't make the partition active or format it! You can set up the swap space partition in an extended disk partition, but a primary partition is a better choice if your disk can support it.
Finally, create the Linux filesystem partition to be whatever size you want; you can even make it the size of the rest of the disk if that's the only partition missing. Again, don't activate or format the partition. When you are running the Linux installation routine, you will identify and format the swap space and filesystem partitions properly.
Using UMSDOS

UMSDOS allows you to use an existing DOS partition to house your Linux system. However, since you will be forcing Linux to use the DOS disk layout, you will suffer some performance limitations compared to creating a dedicated Linux partition. On the other hand, using UMSDOS lets you keep your disk drive the way it is, preventing the hassle of repartitioning and reformatting your drive. It is also a fast and easy way to install Linux if you only want to experiment for a while before installing a full system.
Note that UMSDOS does not let you run DOS and Linux at the same time. UMSDOS (UNIX in MS-DOS) only creates the Linux filesystem under the DOS formatted partition, although the partition is modified to allow long filenames, Linux file permissions, and more. When you start the system, you still have to choose between booting Linux or DOS as the operating system. If you start DOS, you can't use the extended Linux filenames, although you will be able to snoop around the directories. Filenames may not make much sense because of the contraction from long Linux filenames to DOS-compatible filenames, though.
The only limitation about UMSDOS is that the DOS filesystem is not designed as well as the Linux filesystem, so you get some performance degradation. This problem isn't major as most people don't notice the difference unless they are running a file-intensive application like X or compiling programs. You can always start with UMSDOS; then if you decide you like Linux enough, back up the Linux data and repartition the drive to create a true Linux filesystem.
If you want to use UMSDOS, you have to perform a few extra steps when setting up the disk. You must still create the boot and root disks, although you will need a root image that supports UMSDOS. (Most distributions have the root images umsds144 and umsds12 for this purpose.) When you boot Linux and it asks which partition to use for the filesystem, you specify the DOS partition. UMSDOS then initializes the filesystem for you. After that, the procedure for installing the rest of Linux is the same as it is for a dedicated Linux partition.
Installing the Linux Partitions

The Linux installation process starts when you boot your system from the boot floppy disk. After the kernel has loaded, you will be prompted to remove the boot floppy disk and insert your root floppy disk. When the root filesystem has been read, you will either be sent directly to an installation script, or presented with the login prompt. Log in as root. No password is required, because you haven't yet added one to the system.
The first step is to set up the disk partitions, if you haven't already done so, using fdisk. If you have more than one hard drive, you can place your Linux partitions on either drive. If you are planning on keeping a DOS partition, though, make sure that partition is the first partition on the first drive. Linux isn't so picky. If you want to boot Linux cleanly, place a Linux filesystem on the first drive. You can also create Linux filesystems on the second drive. A Linux swap partition can be on either drive, although keeping it on the first drive with the first filesystem is a good idea.
Linux's fdisk

Linux's fdisk program is different than the one in DOS, so check the menus frequently to determine the proper commands. You invoke Linux's fdisk in the same manner as DOS'. If you don't specify a drive, fdisk assumes the first one in the system. Otherwise, you can specifically indicate which disk drive to partition by giving the device name on the command line, as in

fdisk /dev/hdb
which invokes fdisk for the second drive. If your system has IDE, ESDI, or RLL drives, the first drive is /dev/hda and the second is /dev/hdb. SCSI drives are /dev/sda, /dev/sdb, and so on. Because a single controller can support seven SCSI drives, you could have up to /dev/hdg. (You can go even higher with another controller card, but few Linux systems will require that many drives!)
You should not use Linux's fdisk utility to create partitions for operating systems other than Linux. If, for example, you want a DOS partition on your disk, create it with DOS' FDISK. Linux does not write the partition table properly for other operating systems.
As mentioned earlier, Linux's fdisk commands are different than the FDISK commands for DOS. The following list explains the commands you need to run Linux's fdisk utility:
Command
Action
d
Deletes an existing partition
l
Lists all known partition types
n
Creates a new partition
p
Displays the current partition table
q
Quits fdisk without saving changes
t
Changes a partition's type code
v
Verifies the partition table
w
Writes current partition table to disk and exits
Linux's fdisk utility offers quite a few more commands, as Figure 3.3 shows. This screen is the output from the Linux fdisk help (m) command. Note the warning at the top of the screen. This warning is issued whenever your hard drive has more than 1024 cylinders, which early versions of Linux (pre 1.0 kernels mostly) couldn't support. Later versions of Linux, including the version provided on this book's CD-ROM, all support much larger hard drives. The warning is a holdover from the earlier system and should really be taken out.
Figure 3.3. Linux's fdisk utility offers these commands.
The process for setting up a partition is to first examine the partition table to make sure any existing partitions are correct. If you have a DOS partition on your drive, it should show in the partition table. If you created Linux swap and filesystem partitions when you were in DOS' fdisk, they should appear in the partition table too, although the partitions' types will be incorrect.
Setting Up Linux Partitions

To create the Linux swap space partition, use the n command and give the starting sector number. Usually, this number will be immediately after any existing DOS partition (or other operating systems you have installed). Linux's fdisk lets you specify the size of the partition either by supplying an end sector number or by giving a size in megabytes (remember the swap space size has a practical maximum of 16M). If you give the size in megabytes, the format is usually +XXM, where XX is the number of megabytes (such as +16M). You can also specify kilobytes, but you don't want to create a swap partition that is less than 1M.
Most PC BIOSs cannot handle more than 1024 cylinders on a disk drive. You may not be able to create DOS or Linux partitions or filesystems that go beyond the 1,023th cylinder (numbering starts at zero). Some other operating systems, such as SCO UNIX, allow you to use anything beyond the 1,024 limit. Linux can use partitions beyond the 1,024 limit, but it can't boot from them. If you have a disk drive that has more than 1023 cylinders, make sure your primary Linux partition ends before 1023. You can create extra partitions following that cylinder and mount them as second filesystems. Alternatively, you can create a single large Linux filesystem that extends or starts beyond the 1,023rd cylinder and use a LILO boot floppy disk.
The fdisk program asks you whether you want to create a primary or an extended partition. If you are creating a primary partition, the program wants the number (one to four—remember a DOS partition has to be number one to boot). In most cases, you should create only primary partitions, unless you have a large disk drive. You can use extended partitions to add logical drives inside primary partitions, which is similar to the way DOS creates logical drives. In Linux, extended partitions are not the same as extended filesystems!
Some distributions of Linux issue the message Warning: Linux can't currently use X sectors of this partition. This warning was in early versions of Linux that couldn't handle filesystems larger than 64K and can be ignored.
After you have created the Linux partition, assign it a type. Some versions of fdisk prompt for this information right away, and others let you select the option to assign filesystem types from the fdisk menu. In either case, the letter l will display all known filesystem types. Choose the one that designates a Linux swap space (number 82), and check the partition table. Figure 3.4 shows the filesystem types supported by the version of Linux included with this book. As you can see, many filesystem types are allowed, although most users will only use the DOS, Linux swap, and Linux data types. The other filesystem types were included in earlier versions of Linux for compatibility with other operating systems.
Figure 3.4. The filesystem types supported by Linux, identified by type number and description.
Your Linux swap space partition should have the correct size and partition type when you display the partition table with the p command. Although Linux doesn't care about the partition type numbers, some other operating systems do note them, so it's a good practice to label them correctly in order to prevent future problems. This practice also helps you keep the partition table organized.
Next, create your primary Linux filesystem partition in the same manner. If you want to use the rest of the disk drive for that partition, you can enter the end sector number of your drive (Linux's fdisk will tell you the range you can use). This number would be the usual default if your hard drive has a DOS, Linux swap space, and Linux filesystem partition on it. After you have created the Linux filesystem partition, identify its filetype as 82, which is a Linux native type. You can display the partition table at any time with the p command (inside fdisk only). Figure 3.5 shows a partition table set up on a 2.4G SCSI hard drive (/dev/sda), which has 500M for DOS (/dev/sda1), a 16M Linux swap space partition (/dev/sda2), and the rest of the drive for Linux data (/dev/sda3).
Figure 3.5. A completed partition table with DOS and Linux sharing a large (2.4G) drive.
Make a note of the size of the swap space and filesystem partitions, in blocks, as you will need this information later. You can read this information straight from the partition table. After you create the Linux partitions and are satisfied with the partition table layout, save and exit fdisk. Make sure you write the table to disk with the w command. If you don't save the information, you will have to repeat the process again.
Enabling the Swap Space for Installation

Linux's installation routine requires a good chunk of RAM to proceed. If you have 4M of RAM or less, you will have problems installing Linux unless you have the kernel use the swap space partition. (If you have only 4M or less of RAM in your system, you should have a swap space of at least 8M, preferably 16M.) If you try to install Linux and get memory error messages, you system doesn't have enough RAM and the kernel needs to use the swap space. Even if you have lots of RAM, there's no reason not to enable the swap space now. To enable the swap space, issue the command

mkswap -c partition size
where partition is the name of the partition and size is the size of the partition in blocks. If you didn't make a note of this number earlier when setting up the partition table, you can start fdisk again and read the size in blocks from the partition table display.
For example, if you have set up the Linux swap space on partition /dev/hda2 (the second primary partition on the first non-SCSI drive) and it has a size of 13,565 blocks you would issue the command

mkswap -c /dev/hda2 13565
The -c option in the command line tells the mkswap utility to format the partition and check it for bad blocks. This option slows down the creation of the swap partition a little, but a bad block in the swap partition can cause your entire system to crash. If mkswap finds any errors in the swap space, it will generate an error message and mark the block as unusable by the operating system (the block is removed from the total available for swap space). Because mkswap flags bad blocks to be left alone, you can ignore the bad block messages unless there is a considerable number of them (ten or more is a good limit in a 16M partition), in which case your hard drive has too many bad blocks and you should consider either low-level formatting it or replacing it with a new drive.
After you set up the swap partition, you enable the Linux swap space partition with the swapon command. Usually, you have to specify the partition, although some versions use the partition table to figure out the partition automatically. It never hurts to be explicit, though. To enable the swap partition set up in the preceding example, you would enter the command

swapon /dev/hda2
You have to repeat the mkswap and swapon commands for each swap partition, if you created more than one. As soon as you execute the swapon command, the Linux kernel starts to use the new swap space as an extension of the physical RAM. Figure 3.6 shows a swap partition called /dev/sda2 (second partition on the first SCSI drive) being set up and activated. Note that you need to know the size of the partition in blocks. You get this number from the fdisk utility.
Figure 3.6. Setting up and activating a swap partition on /dev/sda2.
If you've turned on the swap space and still get error messages when you try to install Linux, you need either more physical RAM or a larger swap space. Increasing the swap space now and then installing Linux is better than having to redo it later. To increase the size of a swap space partition, you may have to remove the existing Linux partitions and recreate them with fdisk.

Creating the Linux Filesystem Partition

Once you have a swap space configured and working, you can set up the Linux filesystem. Some Linux installation scripts automate this step, or you may have to execute it yourself. Either way, this section explains what is going on.
You have already allocated the partition table to support a Linux filesystem. Now you can create the filesystem with the mkfs (make filesystem) command. The exact format of the command depends on the type of filesystem you are setting up. The most popular filesystem (for reasons of speed and flexibility) is called the Second Extended filesystem (which has nothing to do with extended partitions on a hard disk). To create a Second Extended filesystem, issue the command

mke2fs -c
where partition is the device name and size is the size of the partition in blocks (taken from the partition display in fdisk). For example, to create a filesystem in /dev/hda3 that is 162,344 blocks in size, the command would be

mke2fs -c /dev/hda3 162344
When specifying the size of a partition, make sure you use blocks and not sectors or cylinders. Using the wrong value will result in errors or only a fraction of your partition being used.
The mke2fs utility checks the partition for bad blocks (the -c option), and then sets the filesystem up properly in that partition. If you are setting up a large partition, the disk check can take a few minutes, but you should not skip it unless you know your disk is good.
The other filesystems available to Linux are the Xia filesystem, the Extended filesystem, and the Minix filesystem. The Xia filesystem is good, but not as popular as the Second Extended filesystem. The Extended filesystem is an older version of Second Extended, and the Minix filesystem is compatible with the old Minix operating system (which Linux was written to replace). You can create these filesystems with the following commands:
Extended
mkefs
Minix
mkfs
Xia
mkxfs
All three commands take the same arguments as the Second Extended filesystem command. The Minix filesystem is limited to 64M. None of the mkfs commands format the filesystem; they just set it up. You are prompted for a filesystem format during the installation process.
Installing the Linux Software

After you create and format the partitions and create the filesystems, you can install the Linux software. This step may be automated, depending on the installation procedure included with your Linux distribution. Most versions of Linux include a utility called setup that installs the software for you. From the Linux prompt, type the command

setup
If you are running the color root image, you get graphic, full-screen windows for the installation process. Other root images use character-based installation messages instead. Many users who install Linux frequently avoid the color root image because it can take a little longer to answer all the questions the script poses and some typing errors are difficult to correct. Whichever root image you choose, carefully read each screen.
The setup utility supplied with the Linux system on this book's CD-ROM is shown in Figure 3.7. Some minor variations in menu choices exist between versions of Linux, but the primary options are much the same.
Figure 3.7. The most common setup utility menu.
Linux presents you with many choices during the installation. Although the default choices are correct for most people, check that the default is what you want. You have the option of letting Linux install everything without your prompting, except when disk sets change, but you should use this option only if you know exactly what is going on your disk. If you are installing Linux for the first time or want to choose the software to be installed by examining descriptions of each package, use the verbose options to show all messages and let you control the process.
Selecting the Source and Disk Sets

The setup installation script either asks you or lets you set several pieces of information. First, you need to specify the source of the software. You can usually accomplish this step by by selecting Source from the setup menu when setup starts its automatic installation process. If you have a CD-ROM, it should have been activated during the boot process if the drivers were correct for your hardware. Select the CD-ROM option. You may be asked to further narrow down the type of CD-ROM you have on your system. Choose the exact type(or the one closest to it) and hope for the best. If you are installing from another disk drive partition (such as another Linux partition or a DOS partition), provide the full device and path names. Figure 3.8 shows the Source option choices presented from the setup menu. From here, you can select CD-ROM. If Linux didn't identify your CD-ROM drive when it booted, you may be presented with another screen and asked to choose the type of CD-ROM drive your system has.
Figure 3.8. The Source option on the setup menu lets you select where the Linux software will be read from.
The installation program then asks for the target of the installation. The target is where you want the software to be installed. The newly created Linux partition is probably the location you want, so enter the partition's name. You will probably be asked whether you want to format that partition; answer yes. (Running mkfs or its variants does not format the partition for you.)
Next, Linux displays a list of the disk sets you can install. You may get to this screen through the normal installation process, or you can select Disk Sets from the setup menu. Choose the ones you want. The list of disk sets is usually a scrolling window, as shown in Figure 3.9. Make sure you scroll through the entire list and mark the disk sets you want to install.
Figure 3.9. The scrolling list holds the names of each major package Linux offers.
Some setup versions let you further refine the list of utilities when the disk set is installed. As a last step, verify the information, and then let Linux install itself. If this process doesn't start automatically, choose the Install option from the setup menu. Linux may double-check with you that you want to install the disk sets you've selected. This screen message looks similar to the one shown in Figure 3.10. This is your last chance to change your mind before Linux starts copying files to your hard drive. After you tell Linux to go ahead and install the software, watch for messages and prompts, and follow any on-screen instructions. If you are installing from a floppy disk, you will be prompted at intervals to change to the next disk in the disk set.
Figure 3.10. The Linux installation routine usually stops and prompts you before it starts installing software.
As Linux installs software, it displays status screens like the one shown in Figure 3.11 whenever the disk set is changed. As each piece of software in a disk set is installed, its name, size, and a brief description is often displayed, as shown in Figure 3.12. Occasionally, you will be asked to choose whether to install a particular component, as shown in Figure 3.13. Choosing yes installs the package described on the screen; choosing no (use the scroll key to display the no option) skips that package and moves to the next.
Figure 3.11. As Linux installs each selected disk set, setup displays the letter of the set. The e set being installed here is the GNU Emacs editor.
Figure 3.12. Each package in a disk set that is installed by default is displayed in a status message, along with the size and brief description of the package.
Figure 3.13. Some disk sets contain optional components. When one is encountered, you are presented with a screen like this one that describes the package and asks whether you want to install it.
Creating a Boot Disk

At the end of the installation routine, you may be prompted whether you want to create a boot disk. Figure 3.14 shows this screen from the Linux CD-ROM included with this book. The boot disk enables you to access the system at any time, especially if the normal boot process fails. You should always make a boot disk for emergency purposes. This disk is not the same as the boot floppy disk you made to start the installation (which is only useful when you reinstall from scratch).
Figure 3.14. During the installation process, setup may ask you whether you want to create a boot disk.
When you choose to create a boot disk, Linux prompts you for a floppy disk, as shown in Figure 3.15. Insert a floppy disk in the drive and choose Yes. (Choosing No abandons the creation of the boot disk.) Linux then proceeds to copy the the kernel image and some extra information to the floppy disk. While Linux is creating the boot disk, it shows you a message like the one in Figure 3.16.
Figure 3.15. When you choose to create a boot disk, Linux prompts you to insert a floppy disk in the drive and choose Yes.
Figure 3.16. This screen shows the progress of the creation of the boot disk.
Configuration Details

After installing disk sets and creating a boot disk, the setup routine may give you a choice to continue with the installation process by configuring your system or to leave the configuration until later. It's a good idea to continue with the process because back-tracking can be difficult sometimes. Although the order of prompts and the options presented to you are different depending on the version of the Linux system you are installing, usually you are asked to set up your modem first, as shown in Figure 3.17.
Figure 3.17. The first configuration information you are asked about is your modem.
If you have a modem installed on your system already, choose the Yes option to configure the port and modem speed now. Alternatively, if you are not sure which port you want to use or want to add the modem later, choose No. If you choose Yes to install a modem, you are asked for the device it is attached to, as shown in Figure 3.18. The devices are named in Linux format, with /dev/cua0 equivalent to COM1, /dev/cua1 equivalent to COM2, and so on. Choose the proper device. If your modem is used by DOS' COM2 port, for example, scroll to /dev/cua1 and choose OK. If you are not sure which port to use, try /dev/cua1, as most mouse ports are COM1 (/dev/cua0). You can always reconfigure the system later.
Figure 3.18. Choose the device your modem is attached to by using the Linux /dev/cua conventions.
Next you will be asked whether you want to set up your mouse, as shown in Figure 3.19. You can set the mouse up later, but it's easier to do it when you first load the Linux software. If you choose to configure the mouse at this time, you have to choose the type of mouse you are using. Figure 3.20 shows the list of currently supported mouse types. Most mouse peripherals are serial, so select the serial mouse that matches your unit. If in doubt, choose Microsoft compatible serial mouse.
Figure 3.19. Linux ask you whether you want to set up your mouse.
Figure 3.20. Choose the type of mouse your system uses.
After you choose the mouse, you may be asked for more information about it. If the mouse is a serial mouse, you must choose the port it is attached to, as shown in Figure 3.21. The port numbering is similar to the modem port (although the device name is different), with /dev/S0 corresponding to COM1, /dev/S1 to COM2, and so on. Don't select the same port as the modem! If you are installing a bus mouse, you may be asked for the DMA the mouse uses.
Figure 3.21. For serial mouse units, you must select the port the mouse is attached to.
Finally, you may be asked whether you want to try out some screen fonts. This step is time-consuming and generally unproductive. It is much better to go with the default fonts for now and modify them later if you really don't like them. These fonts are used for all character-based messages.



Setting the Boot Process

The last step in the Linux installation process is setting the boot device. A utility called LILO (Linux Loader) usually boots Linux. LILO can boot your system in several different ways, depending on whether you want to use your system with another operating system. Most of the time, you will want LILO to boot your system into Linux with the option to load DOS (if you have it on your system).
The LILO screens explain most of the choices quite well, but LILO has a few quirks to it. Chapter 4 is devoted to explaining what LILO does and how to make it behave properly. For now, if you are impatient, follow the defaults, but don't let LILO overwrite your hard disk's Master Boot Record. Doing so can cause a bit of a hassle when you want to boot DOS. You can, though, let LILO write a boot sector to your Linux partition, and then use fdisk to make either DOS or Linux active. If you're not too sure what to do with LILO, ignore it for now. You have a boot floppy disk that lets you start your machine. When you better understand LILO, you can set it up the way you want.
As a last step in the installation process, reboot your machine and let Linux boot from the boot floppy disk or from LILO, if you installed it. If everything boots properly, you can use Linux as you normally would. If you experienced problems booting, watch error messages and check the installation process to see which part went screwy. As long as you have your boot disk, you should be able to get into Linux without a problem.
Viewing Installed Software Files

When Linux is up and running, you may want to install or remove disk sets and other software. You can also check that components of a disk set have been properly installed. A few different utilities are available for this task, but the most common is called pkgtool. When you enter the pkgtool command name at the shell prompt, a menu that enables you to install new software, remove existing software, or view installed files in a package appears on-screen. Figure 3.22 shows the pkgtool menu. You can also use the setup utility for these tasks.
Figure 3.22. The pkgtool utility is one way to install, remove, or examine software on your Linux system.
To view the contents of a package, select View from the main pkgtool menu, and then choose the name of the package from the list presented. Figure 3.23 shows the list of packages. The list should include all the disk set tools you have installed, as well as any additional software installed after the first installation. Selecting a tool name sends pkgtool to check all the files that should be in the software and report its success. Sometimes the list of software in a package can take a while to appear. Be patient! The list pkgtool presents usually has a brief description of the tool and a list of all the files in the installation. Figure 3.24 shows the entry for the base software package.
Figure 3.23 When you select View from the pkgtool utility, you must choose which package to view.
Figure 3.24 The pkgtool utility shows the components installed for each package on your system.
When the list of files is displayed, you can move through them with the space bar. To leave the list of files, select the Exit option at the bottom of the screen.
Troubleshooting

Many different problems can occur while setting up and installing a Linux system, although most of them are self-explanatory from error messages. The following sections look at a few of the most commonly encountered problems.
Software Installation Problems

You may encounter a few errors when installing Linux. If you get the message device full, you have run out of disk space and need to either break up the installation into several partitions or install fewer components. If you haven't yet installed the basic system, you need more disk space. You have to delete your partitions and start the installation process again, allocating more space to Linux.
Errors such as read error, file not found and tar: read error are indicative of a problem with either the disk medium you are installing from, or an incomplete disk set. These problems usually occur with floppy disks and may indicate that you have a bad floppy disk. All you can do in most cases is replace the floppy disk with a new one.
Hard Disk and Disk Controller Problems

When Linux boots, it displays a few messages, one of the most important being a partition check. You see messages like the following:

Partition check:

hda: hda1 hda2 hda3

hdb: hdb1 hdb2
In this example, the first non-SCSI disk has three partitions and the second disk has two. Your system's output is probably different, of course. If you don't see any partition information, either the hard disk controller is not recognized properly or the disk drives are not accessible. Check the following potential causes for these problems:
Check the cables inside the computer. The hard disk cable should run from the adapter card to each drive's connector. Make sure the cables are connected in the proper manner (the red strip on the cable is at pin 1 on the connector).
Check that the power connector is attached to each disk drive. Without power, your drive doesn't spin up and Linux can't touch it.
Check the partition table to make sure you created a Linux partition properly.
If the drive is still not working properly with Linux but works OK when you boot DOS, a kernel driver for the hard disk is likely at fault. Some IDE drives, for example, are not as well-behaved (not conforming to the IDE standards) as others, and your IDE kernel driver may not be able to talk to your drives. Try using a different kernel image and see if the problem solves itself. If you are using a SCSI kernel and adapter and the drives are not recognized, use the utilities that came with the SCSI adapter card to force a check of the hard drives. They may have a SCSI ID set incorrectly.
Device Conflicts

One of the most commonly encountered problems is hardware that is not recognized properly. This problem can happen to a CD-ROM, a network card, and even a hard disk. Most of the time, a conflict in the IRQ (interrupt), DMA (Direct Memory Address), or I/O address settings causes this problem. When two devices have the same settings on any one of these three characteristics, Linux and the BIOS may not be able to communicate with the device properly.
A symptom of this problem may be Linux hanging when it tries to find a specific device, as explained in the boot messages. When Linux boots up, it generates messages that explain what it is doing. If you see a message that it is trying to connect to the network card, for example, and it never gets past that point, chances are that the network card has a conflict with another device. (Totally failed cards are very rare and don't usually stop the boot process, as Linux ignores devices it can't access. The problem with a working card with conflicting settings is that Linux is getting messages from two devices that don't act the same.)
To check for conflicts, run a diagnostic utility under DOS, such as MSD or Norton Info. These utilities can show you the current IRQ, DMA, and I/O addresses and pinpoint any conflicts. you can also use them to find available settings. Alternatively, you can check the settings of every device in your system for conflicts. Usually, network cards conflict with sound boards, non-SCSI tape driver cards, video cards, and similar add-on cards. Most cards use DIPs or jumpers to set these parameters, so check them against the documentation. To help isolate the problem, remove cards that are not necessary, such as a sound card, and see whether the boot process moves past the device that caused the hangup.
Another problem that can occur is with SCSI devices (and a few others, although much rarer) that must have specific settings in the kernel image. Some kernels, especially special-purpose kernels that have been developed for non-mainstream adapters, were compiled with settings that are default values for adapters or disk drives, and if the settings have been changed, the kernel hangs up. To check for this type of problem, investigate any documentation that came with the kernel image.
The most common devices in a PC (COM ports, parallel ports, and floppy disks) and their IRQ, DMA, and I/O addresses are shown in in the following list. These are the default values for a PC, but they may be changed by users. Because only two COM ports (serial ports) are usually supported by DOS, they share IRQ values. The I/O addresses are different, though. Both floppy disks share the same I/O addresses, IRQ, and DMA.
Device
IRQ
DMA
I/O Address (Hex)
COM 1 (/dev/ttyS0)
4
N/A
3F8
COM 2 (/dev/ttyS1)
3
N/A
2F8
COM 3 (/dev/ttyS2)
4
N/A
3E8
COM 4 (/dev/ttys3)
3
N/A
2E8
LPT 1 (/dev/lp0)
7
N/A
378-37F
LPT 2 (/dev/lp1)
5
N/A
278-27F
Floppy A (/dev/fd0)
6
2
3F0-3F7
Floppy B (/dev/fd1)
6
2
3F0-3F7
You may have noticed that the serial ports are called /dev/ttyS0, /dev/ttyS1, and so on in the list of devices. Yet they were called /dev/cua0, /dev/cua1, and so on when you configured the modem. The ports are the same (/dev/ttyS0 is the same as /dev/cua0); Linux just handles the devices differently. Don't get too confused about these device driver names yet. Just remember that /dev/cua refers to a modem port.
Network cards, SCSI adapters, sound boards, video cards, and other peripherals all must have unique IRQ, DMA, and I/O addresses, which can be difficult to arrange with a fully loaded system. For more information on available values, check your device or card installation manual for recommended values and potential conflicts.
SCSI Problems

SCSI is one of the most versatile interfaces, and it pays for that versatility in potential problems. Linux is usually good about reporting problems with SCSI devices, although the error messages may leave you wondering about the real cause of the problem.
The following list explains many of the common SCSI errors and their probable causes. Find the message that closely matches the error message Linux displays to determine your corrective steps.
SCSI device at all possible IDs
One or more devices is at the same SCSI ID as the controller. Check and change device IDs. Controllers should be ID 7.
Sense errors
This error is probably caused by bad termination. Check that both ends of the SCSI chain are terminated. If that is not the problem, the cable is likely at fault.
Timeout errors
This error is usually caused by a DMA, IRQ, or I/O address conflict. See the preceding section for more information.
SCSI adapter not detected
The BIOS is disabled or the kernel doesn't recognize the SCSI adapter. Check the drivers.
Cylinders Beyond 1024
Your disk has more than 1,024 cylinders, which the PC BIOS can't handle. Linux can use more than 1,024 cylinders, but it can't boot from a partition that extends across that cylinder boundary.
CD-ROM drive not recognized
Some CD-ROM drives require a CD in the drive to be recognized properly. Insert a CD and reboot.

Problems Booting Linux

If you have installed Linux and the system doesn't boot properly from your hard disk, it may be a problem with LILO or with the partitions. If you created a boot floppy disk, boot from that. If that boots without a problem, check the partition table by executing fdisk. Make sure the Linux partition is active. If it is and you still can't boot from the hard disk, boot from the floppy disk and run LILO again to configure the boot sector. See Chapter 4 for more information on LILO.
A problem will sometimes occur when Linux can't find the main Linux partition. Boot from the floppy disk and hold down the Shift or Ctrl key. This will produce a menu that enables you to specify the boot device explicitly. This problem can usually be corrected with LILO.
Booting, init, and Shutdown

The most basic tasks you face with a Linux system are starting the machine properly and shutting it down when you are finished. Although the two processes sound simple, there are several ways of accomplishing each task and several hazards associated with performing the processes incorrectly. UNIX, as a whole, doesn't like shocks to the filesystem, such as fast power-offs, so you must carefully shut down the system to preserve your information.
This chapter looks at the startup and shutdown procedures used with Linux and the init daemon. The init daemon is probably the most important process running on any Linux system. Understanding what init does and how to use it properly can help you on the way to getting the best performance from your Linux system.
Starting Linux

Starting the Linux system can be as simple as turning on the power switch of your PC. If Linux is configured to autoload, Linux will be up and running after a few seconds. Few systems are set up to run only Linux, though, and even fewer have it boot automatically when the power is turned on. Although automatic startup is convenient, many Linux users prefer to be able to choose which operating system to boot into (if other operating systems are loaded on the system) or to change the level of access to Linux.
You can start a Linux system by using a boot floppy disk or using LILO in one of several configurations. Each method has benefits and potential problems, which are discussed in the following sections.
Using LILO to Boot

LILO is the most common user method of booting a Linux system because it doesn't involve using a boot floppy disk. Chapter 4, "LILO," examined LILO in detail. LILO is a program that sits in the boot sector of a disk partition or the master boot record of the entire hard disk and points to the partition and location of the Linux kernel image.
If LILO is installed as a first-stage boot loader (meaning it boots Linux automatically), Linux starts to boot whenever the power is turned on. If you want to halt the boot process, you can use the Ctrl+Alt+Del sequence when the machine starts the boot sequence. (You must be careful when you hit Ctrl+Alt+Del, as you may reboot the machine by accident. Wait until you see the loader start its actions.) The Ctrl+Alt+Del sequence instructs LILO to pause and display the following prompt:

Boot:
From this boot prompt, you can tell LILO which operating system to load (DOS, Linux, OS/2, and so on). If you press the Tab key when the boot prompt is displayed, LILO displays a list of all partitions and operating systems it knows about. The operating system partitions must have their configuration information included in the LILO information. Providing this information is simply a matter of identifying the partition device name and a name for the operating system when you are creating the LILO configuration file. Chapter 4, "LILO," covered these steps.
Because LILO writes data to the disk drive that other operating systems cannot read, it is not always the best solution if you install and remove operating systems frequently from your hard disks. Whenever you make changes to the configuration of your Linux system or other partitions on the hard disk, update the LILO information by rerunning LILO.
Using a Boot Floppy Disk

If you don't want to rely on LILO (which modifies disk sectors and may cause problems when you use several operating systems or change operating systems frequently), you can use a boot floppy disk to start up Linux. A boot floppy disk is a single floppy disk that contains a complete copy of the Linux kernel and instructions for accessing the root partition on your hard drive. The boot floppy disk must be of the proper format to run on the first disk drive on your system (drive A in DOS terms). Linux cannot boot from a second (drive B) floppy disk drive.
In many ways, a boot floppy disk is the easiest and most versatile method of starting Linux. If, for example, you have your hard disk partitioned to contain both DOS and Linux, with DOS the normal boot partition, simply turning on your PC boots DOS without a hitch. If you want Linux to boot, you insert the boot floppy disk and start the machine. Linux boots from the floppy disk, and then accesses the hard drives as if it had booted from them.
If you are using a boot floppy disk to start Linux, be sure to update the kernel image on the floppy disk every time you make a change to the system that involves rebuilding the kernel. Keep in mind that you must rebuild the kernel almost every time you add devices or device drivers. Use the procedure outlined in the following paragraphs to update your existing floppy disk, or, even better, create a new floppy disk and save your current floppy disk for emergencies. You are not prompted to create a new boot floppy disk when you make changes to the kernel, so you must remember to perform this step.
To create a boot floppy disk, you need a blank, formatted, high-density floppy disk (1.44M or 1.2M, depending on the A drive on your system). Format the floppy disk under DOS to lay down the sector and track information properly for Linux to read. Some small kernels can fit on low-density floppy disks, but high-density drives are most likely to be used on your system because they are the standard. The high-density floppy disk can have information on it as well as the Linux kernel, but make sure you have enough disk space for the kernel image.
Some versions of Linux (such as Slackware) can create the boot floppy disk as part of the normal setup routine. If you are using a distribution that has a setup routine, try choosing the Configure option on the menu, follow through the prompts, and see whether you are prompted to create a boot floppy disk at the end. Alternatively, some distributions have a separate menu option for creating the boot floppy disk.
If you want to create the boot floppy disk manually, locate the Linux kernel on your system. Usually it is in the root directory. The kernel name changes depending on the version of Linux, but it is often called Image or vmlinux. Some versions of Linux store the kernel image in the /etc directory.
Some versions of Linux also store the kernel in a compressed format. The names of compressed kernels end in z, as in vmlinuz or vmlinux.z. A compressed kernel takes up less space on the hard disk or floppy disk, and it is decompressed when the Linux kernel boots. A compressed kernel takes a little longer to load than a kernel that isn't compressed, but because it is decompressed only when the system boots, the trade-off is usually beneficial (unless you have tons of empty disk space).
You should be able to find the kernel quite easily by watching the startup messages when you boot the system and noting the kernel name, and then using find or whereis to locate it. Much easier is to change to the root directory and look for a large file called Image or vmlinux. The file is owned by root and has only read permission in many distributions of Linux. For example, when you do a listing command (such as ls-l), you see an entry like the following:

-r-------- 1 root root 457700 Aug 10 13:52 vmlinuz
This entry shows a kernel image file of almost half a megabyte that is compressed. The date and time of the kernel match the last time you rebuilt the kernel or the time and date you installed Linux.
Once you have identified the kernel file, instruct Linux that the file is the root device and indicate which partition it is on by using the rdev command. For example, to set the root device to the kernel vmlinuz in the root directory of the partition /dev/sda3, you would issue the command

rdev /vmlinuz /dev/sda3
Because you must specify the path to the kernel completely, the leading slash is included to show the root directory.
If you issue the rdev command by itself, it displays the current partition of the root filesystem:

$rdev

/dev/sda3 /
You can use this command to check the current settings if you are not sure which partition is your root filesystem. (This chapter looks at the rdev command in a little more detail in a later section.)
After you set the root device, you can copy the kernel to your formatted floppy disk. Use the cp command and the device name of the floppy disk:

cp /vmlinuz /dev/fd0
Once the image file has been transferred, the floppy disk should be able to boot Linux. If it doesn't, either the image didn't transfer properly due to a lack of disk space or a corrupted disk sector, or there is a problem with the kernel image.


Creating and Using a Maintenance Disk

Every system should have a maintenance disk (also called an emergency boot disk) that you can use to boot the Linux system in case anything happens to the boot system (such as LILO). A maintenance disk is a combination boot and root disk that boots a complete Linux kernel independent of your hard disk installation. After you load the maintenance disk, you can use it to mount the hard disk and check for problems, or use one of the hard disk utilities to rebuild LILO or the kernel, depending on the problem with the drive.
To create a maintenance disk, you create a root filesystem on a floppy disk, copy essential tools to it, install LILO, and then make the disk bootable by copying the kernel. Perform this process every time you make a change to the Linux kernel so that your maintenance disk has the same kernel build. Keeping your maintenance disk up-to-date prevents hassles with utilities and devices.
You probably already have a set of maintenance disks in the pair of floppy disks you used to install Linux in the first place. Although these disks are not configured for your system, you can use them to load Linux and mount your hard drive. Many Linux setup procedures have a built-in routine to create boot floppy disks. You can use this routine to create the maintenance floppy disk.
If you have to boot off the maintenance floppy disk for any reason, mount the existing hard drive with the mount command. For example, if you are booting off your floppy disk and want to mount the partition /dev/sda2 (which wouldn't boot Linux for some reason), issue the command

mount -t ext2 /dev/sda2 /mnt
which mounts the hard drive partition under the directory /mnt. The directory must exist before you perform this operation, and it should be empty. The -t option specifies the file type. If your filesystem is not an extended filesystem, change the type.
Shutting Down Linux

The temptation to treat Linux like DOS can be overwhelming when you are ready to finish with your session. Simply turning off the power should shut down everything, right? Well, it does, but it also can completely corrupt all the contents of your hard disk partition, as well as lose any information you were just working on. Granted, that's a very rare and extreme case, but arbitrarily turning off the power to a Linux session is still a bad idea.
Linux manages the hard disk and user spaces in RAM, using i-node tables to maintain the disk information and a memory manager for user information. Linux writes any changes to the i-node tables to the disk drive every so often, but it maintains the RAM copies as the most recent because of RAM's greater speed. If you shut down the power before Linux writes any changes to the disk, the disk contents and the i-node tables written on the disk may not match, causing lost files and an incorrect list of what disk space is available. Even worse, if Linux was in the process of writing the i-node table or any other information at the moment the power is turned off, the write process is interrupted, and disk head crashes or bad sector information can result. The same principle applies to any processes that are running. If, for example, you were running a database reindex when you killed the power, the indexes and databases may be corrupted. Shutting down the Linux system properly makes sure that all processes write and close all open files and terminate cleanly.
There are two easy ways to shut down the Linux system properly. The easiest is to use the Ctrl+Alt+Del sequence. On many Linux versions, this keyboard combination issues a shutdown command that closes all the processes properly, and then reboots the machine. Linux essentially traps the Ctrl+Alt+Del sequence and uses it to shut down the machine. Not all versions of Linux support this sequence, though, so check your documentation carefully.
If your system doesn't trap Ctrl+Alt+Del and reboots the machine when you issue it without shutting down Linux properly, it's the same effect as turning off the power. Make sure your Linux version supports this command before you use it!
The other method of shutting down Linux is with the UNIX command

shutdown
When you issue the shutdown command, Linux starts to terminate all processes and then shuts down the kernel. The shutdown command displays several different messages, depending on the version of Linux, but all inform you of the process or check that you really want to shut down the system.
The shutdown command allows you to specify a time until shutdown, as well as an optional warning message to be displayed to all users logged in. The format of the command is

shutdown time message
As an example, this command

shutdown 15 'Backup Time!'
shuts down the system after 15 minutes and display the message "Backup Time!" to all users on the system, prompting them to log off. This command is handy when you enforce a policy of shutting down at specific intervals, either for maintenance or backups.
In most versions of Linux, the shutdown command accepts the -r option. This option causes the PC to reboot after the shutdown has occurred. You can use this option to reboot to another operating system or to restart Linux after making changes to the kernel or devices. You can use the -r option with a time or message, if you want. The command

shutdown -r 5
reboots the system after five minutes.
In most cases, using Ctrl+Alt+Del or the shutdown command results in the display of a number of status messages on the main console. When Linux has finished shutting down the system, you see the message

The system is halted
When this message appears on-screen, it is safe to shut off the system power or reboot the machine. Although it may seem a little strange to have to follow these extra steps, you will find that many high-end operating systems such as UNIX (and even Windows NT and Windows 95) require you to follow a specific shutdown procedure to prevent loss of information. Get in the habit!
Understanding the init Daemon

The init daemon is usually invoked as the last step in the booting of the Linux kernel. The init daemon is one of the most important Linux daemons because it creates processes for the rest of the system. The init daemon is executed when Linux starts and stays active until Linux is shut down. Understanding what init (and its linked utility telinit) does and how it controls the operating system is important to better administering the Linux system.
Both init and telinit use several configuration files to perform their tasks, so the following sections look at those files in detail, too. These files are closely involved in the starting and stopping of terminals and console sessions. The init program is usually kept in the /bin directory, although some versions of Linux keep it in /sbin. The same directories apply to the telinit utility. The configuration files are always kept in /etc, though.


Run Levels

When the init daemon is executed, it reads instructions from the file /etc/inittab, which is primarily used to start getty processes for terminals and other processes required by Linux. While examining the /etc/inittab file, init searches for an entry labeled initdefault, which sets the default initial run level of the system. If no initdefault level is defined in the /etc/inittab file, the system prompts for the level.
A run level is a particular set of processes ranging from a bare minimum for system administration only to a full operation supporting all configured devices. Run levels are defined by a number from zero to six. An additional superuser level (often called single-user level as only root can log in) is defined as s. The init daemon knows which processes are associated with each run level from information in the /etc/inittab file.
When you use the s run level to display the system in single-user mode, the /etc/inittab file is not read. Instead, the utility /bin/su is invoked for the system console (defined by /dev/console). The init process can save the current state of a system when instructed to change to single-user mode from a higher run level. With some versions of init, the current state of the system is saved in a file called /etc/ioctl.save by the program ioctl. When the console is restarted to a higher run level, the states in this file are restored. If no ioctl.save file is found, the default states are used.
When starting up into multiuser mode (run levels higher than single-user mode), the init daemon performs any entries identified by the instructions boot and bootwait in the /etc/inittab file. Following these instructions usually allows filesystems to be mounted. After these instructions are processed, the rest of the entries that match the selected run level are executed.
The run level of the system can be changed by a user with access to the commands that affect the level. This access is usually restricted to the system administrator for security reasons. You change the run level by using the utility program /etc/telinit (which is linked to /etc/init). The telinit utility is responsible for sending messages to the init daemon to alter the current run level to the requested new level. To alter the run level, add the required level (zero through six or s) to the telinit command. For example, the command

telinit 2
changes the run level to level two and causes init to reread the /etc/inittab file and execute all processes for that level or terminate those for higher levels. To drop into superuser (single-user) mode, use the s option:

telinit s
When switching to the superuser level, you can use either an uppercase or lowercase s. The telinit and init utilities can handle both cases.
You can specify a time delay for the change, in seconds, after the -t option. The command

telinit -t5 3
changes the run level to level three after five seconds. If no time is specified, Linux uses the default value of 20 seconds.
When you change the run level, init sends a SIGTERM warning signal to all processes that are not valid with the new run level. After sending the SIGTERM signal, init waits the specified number of seconds (or the default 20 seconds), and then terminates the process forcibly.
If a process started by init has spawned new processes that are not in the same process group, init doesn't terminate them when you change the run level. You must terminate these processes manually.

The /etc/inittab File

As mentioned previously, the /etc/inittab file is tied closely to the init daemon. Look at the /etc/inittab file on your system to understand which processes are started and which run level is invoked when Linux starts. Extracts from a sample /etc/inittab file show the processes involved in starting the system with init. The first section in the sample /etc/inittab file identifies the default run level, in this case level five:

id:5:initdefault:
The next section in the /etc/inittab file handles the system startup through the files in the /etc/rc.d directories:

si:S:sysinit:/etc/rc.d/rc.S
Following this section is a pointer to the file /etc/rc.d/rc.K, which is used when the system enters the single-user run level:

su:S:wait:/etc/rc.d/rc.K
Next is a pointer to the file /etc/rc.d/rc.M for when the system is started in multiuser level (any one of the levels one through six):

rc:123456:wait:/etc/rc.d/rc.M
The most common run level is five, which is the normal operating level for Linux in multiuser mode. Most installations seldom use the other levels, although they can be used in some circumstances to control access to peripherals. Run levels are best left as the system wants them to prevent problems. This means using run level s for superuser mode and run level five for general use.
Because Linux runs on PC machines, it can support the "three-fingered salute" or Ctrl+Alt+Del sequence. This sequence is not usually supported on PC UNIX systems, so a special instruction is mapped to the sequence in the /etc/inittab file:

ca::ctrlaltdel:/sbin/shutdown -t3 -rf now
When the Ctrl+Alt+Del sequence is intercepted, the system begins a shutdown as shown by the command at the end of the preceding line.
The /etc/inittab file then holds an instruction to start a getty process for each terminal and virtual screen on the system. This sample /etc/inittab file starts six virtual screens (tty1 through tty6) and two serial lines (ttyS0 and ttyS1):

c1:12345:respawn:/sbin/agetty 38400 tty1

c2:12345:respawn:/sbin/agetty 38400 tty2

c3:45:respawn:/sbin/agetty 38400 tty3

c4:45:respawn:/sbin/agetty 38400 tty4

c5:45:respawn:/sbin/agetty 38400 tty5

c6:456:respawn:/sbin/agetty 38400 tty6

s1:45:respawn:/sbin/agetty 19200 ttyS0

s2:45:respawn:/sbin/agetty 19200 ttyS1
The terminal and serial line instructions are examined in more detail in Chapter 11, "Terminals and term."
The lines in the /etc/inittab file follow a specific format. The format follows this pattern:

ID:runlevel:action:process
The ID is a one- or two-character string that uniquely identifies the entry. In most cases, this string corresponds to the device name, such as 1 for tty1, 2 for tty2, and so on. The runlevel decides which of the run levels the line applies to (varying from zero to six). If no entry is provided, then all run levels are supported. Multiple run levels may be identified in the field.
The action indicates the command to execute when init reads the line. The following items are all valid entries for the action field:
The boot action runs when inittab is first read.
The bootwait action runs when inittab is first read.
The initdefault action sets the initial run level.
The off action terminates the process if it is running.
The once action starts the process once.
The ondemand action always keeps the process running (the same as respawn).
The powerfail action executes when init gets a power fail signal.
The powerwait action executes when init gets a power fail signal.
The sysinit action executes before accessing the console.
The respawn action always keeps the process running.
The wait action starts the process once.
If init senses a powerfail condition (such as termination of power to the PC signaled by an Uninterruptible Power Supply) and the system was in multiuser mode, some special powerfail conditions are executed upon restart. These conditions usually check the filesystem for problems prior to bringing the system back up. The /etc/inittab file can contain specific instructions for these conditions, as shown in the following code:

# What to do when power fails (shutdown to single user).

pf::powerfail:/sbin/shutdown -f +5 "THE POWER IS FAILING"

# If power is back before shutdown, cancel the running shutdown.

pg:0123456:powerokwait:/sbin/shutdown -c "THE POWER IS BACK"

# If power comes back in single user mode, return to multi user mode.

ps:S:powerokwait:/sbin/init 5
All these powerfail conditions assume that some device manages to send the powerfail signals to the init process. Special device drivers that interface with UPSs usually do this.
The init daemon doesn't terminate when it has finished reading /etc/inittab. It stays active and monitors the system for specific instructions to change the run level (from a telinit command). It is also responsible for watching all the processes it started, including the getty processes for terminals. Whenever a process init started (called a child process, with init as the parent process) is terminated for any reason, init records the event and a reason for the termination (if possible to identify) in the files /etc/utmp and /etc/wtmp.
Whenever init senses the termination of a a child process, a power fail signal, or a run level change, it rereads the /etc/inittab to check for instructions. You can make changes to the inittab file (using any ASCII editor) while the system is running, but the changes will not be effective until the system reboots or one of the reread conditions occurs. An alternative is to use the q argument to force init to reexamine the /etc/inittab file. To force a reread of the /etc/inittab file, issue the command

init q
The init process checks how many times it has to restart (respawn) a process. If a process must be restarted more than 10 times in a two minute period, init assumes that there is an error in the command line of /etc/inittab for that process and generates an error message on the system console. The init process then refuses to respawn that process for five minutes or until it's forced to restart by the superuser. This step is useful because it prevents the system from wasting CPU cycles when a typographic error was made in the /etc/inittab file.
Using the rdev Family

The rdev command is a utility not just for identifying the root device, as shown earlier in this chapter (it's used when creating a boot floppy disk), but for obtaining all kinds of information about your Linux system and making some configuration changes. The rdev utility can be cumbersome to use, and many administrators ignore it and its companion utilities completely.
If you use LILO to boot Linux, you can ignore all the rdev commands as these parameters are set in the LILO configuration. The only times you will need rdev is when you change kernels and want to make a boot floppy disk for emergency use, or you want to change the RAM disk size. If you don't use LILO, you may occasionally need to use the rdev commands, although it is rare that they will be necessary as the Linux setup procedures define most of these parameters for you. The exception is changes in RAM disk size.
When run by itself, rdev displays the currently defined root partition and directory:

$dev

/dev/sda3 /
In this example, /dev/sda3 (third partition on the first SCSI hard disk) is the current root partition. You can use rdev to change the root partition and point to the kernel image to be used by Linux by providing both parameters as arguments:

rdev /vmlinuz /dev/sda3
This command changes the kernel image used to vmlinuz in the root directory of the third partition. You usually perform this command only when you create an emergency floppy disk.
The rdev command has several options for changing the way it acts, as shown in the following list:
-h
Displays help
-r
Makes rdev act like the command ramsize (see below)
-R
Makes rdev act like the rootflags command (see below)
-s
Makes rdev act like the swapdev command (see below)
-v
Makes rdev act like the vidmode command (see below)
Although you can use these options to alter rdev's behavior, you can also use the following commands directly:
The ramsize command specifies the size of the RAM disk in kilobytes.
The rootflags command enables you to mount the root directory as read-only.
The swapdev command identifies the swap device.
The vidmode command specifies the video mode.
In order to change many of the parameters, you must specify an offset that indicates the decimal value of the kernel location with the rdev command, which is why many administrators don't like the command. To use rdev or one of the utilities in its family, you must calculate the offsets according to the following rules:
Offset 498
Root flags
Offset 504
RAM disk size
Offset 506
VGA mode
Offset 508
Root device
The rootflags command has many options, only one of which really works to enable you to mount the root directory as read-only. Because this feature is seldom (if ever) necessary, most administrators can effectively ignore the rootflags command. (If you are running off a CD-ROM or from a small hard drive that contains only the binaries, you may want to consider using rootflags, but because you can accomplish the same task using file permissions, there's not much need to use rootflags.)
The vidmode command (or rdev -v) lets you change the video mode. If you issue the vidmode command by itself with some versions of Linux, it displays the current settings. More recent versions (including the one on this book's CD-ROM) show a help screen:

$ vidmode

usage: rdev [ -rsv ] [ -o OFFSET ] [ IMAGE [ VALUE [ OFFSET ] ] ]

rdev /dev/fd0 (or rdev /linux, etc.) displays the current ROOT device

rdev /dev/fd0 /dev/hda2 sets ROOT to /dev/hda2

rdev -R /dev/fd0 1 set the ROOTFLAGS (readonly status)

rdev -s /dev/fd0 /dev/hda2 set the SWAP device

rdev -r /dev/fd0 627 set the RAMDISK size

rdev -v /dev/fd0 1 set the bootup VIDEOMODE

rdev -o N ... use the byte offset N

rootflags ... same as rdev -R

swapdev ... same as rdev -s

ramsize ... same as rdev -r

vidmode ... same as rdev -v

Note: video modes are: -3=Ask, -2=Extended, -1=NormalVga, 1=key1, 2=key2,...

use -R 1 to mount root readonly, -R 0 for read/write.
The legal values for vidmode are as follows:
-3
Prompt
-2
Extended VGA
-1
Normal VGA
0
The same as pressing 0 at the prompt
1
The same as pressing 1 at the prompt
2
The same as pressing 2 at the prompt
n
The same as pressing n at the prompt
You can change the video mode using one of these values on the command line or using a number or letter to emulate pressing a value at the prompt.
Logins

All access to a Linux system is through a user account. Every user account must be set up by the system administrator, with the sole exception of the root account (and some system accounts that users seldom, if ever, use). Although many Linux systems only have one user, that user should not use the root account for daily access. Most systems allow several users to gain access, either through multiple users on the main console, through a modem or network, or over hard-wired terminals. Knowing how to set up and manage users accounts and their associated directories and files is an important aspect of Linux system administration.
This chapter looks at the root login, which is the most powerful user account there is. From there, the chapter examines several aspects of setting up new user accounts on your Linux system. This chapter also looks at groups and how they are involved in the Linux system.
Understanding the Superuser Account

When you install the Linux software, one master login is created automatically. This login, called root, is known as the superuser because there is nothing the login can't access or do. Although most user accounts on a Linux system are set to prevent the user from accidentally destroying all the system files, for example, the root login can blow away the entire Linux operating system with one simple command. The root login has no limitations.
The sheer power of the root login can be addictive. When you log in as root you don't have to worry about file permissions, access rights, or software settings. You can do anything at anytime. This power is very attractive to newcomers to the operating system, who tend to do everything while logged in as root. It's only after the system has been damaged that the root login's problem becomes obvious—there are no safeguards! As a rule, you should only use the root login for system maintenance functions. Do not use the superuser account for daily usage!
The root login should be kept only for those purposes where you really need it. Change the login prompt of the root account to clearly show that you are logged in as root, and think twice about the commands you issue when you use that login. If you are on a stand-alone system and you destroy the entire filesystem, only you are inconvenienced. If you are on a multiuser system and insist on using root for common access, you will have several very mad users after you when you damage the operating system.
So after all those dire warnings, the first thing you should do on a new system is create a login for your normal daily usage. Set the root password to something other users of the system (if there are any) will not easily guess, and change the password frequently to prevent snooping.
You also can create special logins for system administration tasks that do not need wide-open access, such as tape backups. You can set a login to have root read-only access to the entire filesystem to decrease the potential for damage. This login lets you back up the system properly, but prevents you from erasing the kernel by accident. Similar special logins can be set up for e-mail access, gateways to the Internet, and so on. Think carefully about the permissions each task requires and create a special login for that task; your system will be much more secure and have less chance of accidental damage.
The most important thing to note is that the superuser account doesn't have to be called root, although this account is created automatically as root when Linux installs itself. In theory, this account can have any name, but the name root is almost always used. The superuser account is always defined as the account with a user ID number of zero. User ID numbers are defined in the /etc/passwd file.
Establishing User Accounts

Even if you are the only user on your Linux system, you should know about user accounts and managing users. You need to know how to establish a user account because you should have your own account (other than root) for your daily tasks. If your system lets others access the operating system, either directly or through a modem, you should create user accounts for everyone who wants access. You may also want a more generic guest account for friends who just want occasional access.
Every person using your Linux system should have their own unique user name and password. The only exception is a guest account or perhaps an account that accesses a specific application such as a read-only database. By keeping separate accounts for each user, your security is much tighter, and you have a better idea of who is accessing your system and what the user is doing. A one-to-one correspondence between users and accounts makes tracking activities much easier.
The file /etc/passwd contains all the information about user accounts. The /etc/passwd file should be owned only by root and should have its group ID set to zero (which usually indicates a root or system group, as defined in the /etc/group file). Set the permissions of the /etc/passwd file to allow write access by root only; all other accounts can have read access. (Groups and permissions are dealt with later in this section.) The lines in the /etc/passwd file are divided into a strict format:

username:password:user ID:group ID:comment:home directory:login command
To understand this format, look at a sample /etc/passwd file. The following /etc/passwd file is created when a Linux system is newly installed:

root::0:0:root:/root:/bin/bash

bin:*:1:1:bin:/bin:

daemon:*:2:2:daemon:/sbin:

adm:*:3:4:adm:/var/adm:

lp:*:4:7:lp:/var/spool/lpd:

sync:*:5:0:sync:/sbin:/bin/sync

shutdown:*:6:0:shutdown:/sbin:/sbin/shutdown

halt:*:7:0:halt:/sbin:/sbin/halt

mail:*:8:12:mail:/var/spool/mail:

news:*:9:13:news:/usr/lib/news:

uucp:*:10:14:uucp:/var/spool/uucppublic:

operator:*:11:0:operator:/root:/bin/bash

games:*:12:100:games:/usr/games:

man:*:13:15:man:/usr/man:

postmaster:*:14:12:postmaster:/var/spool/mail:/bin/bash

nobody:*:-1:100:nobody:/dev/null:

ftp:*:404:1::/home/ftp:/bin/bash
Each line in the /etc/passwd file is composed of seven fields separated by a colon. If nothing is to be entered in a field, the field is left blank, but the colons are retained to make sure each line has seven fields (which also means each line will have six colons). The seven fields (from left to right on each line) are as follows:
The user name is a unique identifier for the user.
The password is the user's password (encrypted).
The user ID (UID) is a unique number that identifies the user to the operating system.
The group ID (GID) is a unique number that identifies the user's group (for file permissions).
The comment is usually the user's real name, but sometimes it is a phone number, department, or other information.
The home directory is the directory in which the user is placed when he or she logs in.
The login command is the command executed when the user logs in; normally, this command starts a shell program.
You should know what each field does and how other programs on your Linux system use it. Note that this type of user file is used with almost every UNIX system in the world, so once you know it for Linux, you know it for most UNIX versions.
User Names

The user name is a single string, usually eight characters or less, that uniquely identifies each user. Because the user name is the basis of most communications between users and other machines, the user name you use (or assign to others) should be simple and obvious. Usually, this name is a permutation of the user's real name. A typical user name may be a combination of the user's first and last names, such as tparker or timp. A user name composed of the first initial and last name is fairly common in large networks.
Note that the characters in these examples are all lowercase. Case is important in Linux (as with all UNIX versions), so tparker and Tparker are two different logins. Because most Linux commands are lowercase, the convention is to also keep user names lowercase. Underscores, periods, numbers, and some special characters are allowed, but they should be avoided because they make login names look strange and can also cause problems for some applications.
Small systems, such as one comprised of a single machine, may use more familiar names, such as the user's first name. A small system may have users with the names tim, bill, yvonne, and so on. If two users have the same name, there must be some method to differentiate between the two (such as bill and billy).
A few users like to create cryptic user names that reflect their hobbies, nicknames, pets, lifestyle, or personality. You may find user names like vader, grumpy, wizard, and hoops. This type of naming is fine on small systems that are used by one or two users, but it quickly becomes awkward on larger systems where other users may not know their coworker's user names. On the whole, if more than a couple of friends use your system, discourage this type of user name.
Passwords

The system stores the user's encrypted password in the password field. This field is very sensitive to changes, and any modification to it can render the login useless until the system administrator performs a password change. Only the system administrator or the user can change the password by using the passwd command.
Some versions of UNIX do not keep the passwords in the /etc/passwd file because of potential security problems. If the password fields on your system are all set to x, then another file (called a shadow password file) is in use. However, all versions of Linux currently available do use this field by default. Systems running either Yellow Pages or NIS (Network Information Service), both of which rely on a central file of user names and passwords, do not use the password field. Few Linux systems use either YP or NIS, however, so you can ignore this distinction for the moment.
When a user logs in, the login program logically compares the password the user typed to a block of zeros, and then compares that result to the entry in the password field. If they match, the user is granted access. Any deviation causes login to refuse access.
You can use this field to restrict access to the system. If you want to prevent a login from ever being used for access, such as a system login like lp or sync, place an asterisk between the two colons for the password field. This asterisk restricts all access. In the sample /etc/passwd file shown previously, many system logins have an asterisk as their password, effectively blocking access.
You can also use this field to allow unrestricted access by leaving it blank. If no password entry exists (the field has nothing in it), anyone using the user name is granted access immediately, with no password requested. Do not leave passwords open unless you are using your Linux system for your own pleasure and have nothing of value on the filesystem.
Don't attempt to put a password directly in the password field using an editor. You cannot recreate the encryption method, and you'll end up locking the user account out. Then only the system administrator will be able to change the password and allow access.
User ID

Every user name has an associated, unique user ID. Linux uses the user ID, also called the UID, to identify everything associated with the user. The user ID is preferable to the user name because numbers are easier to work with than the characters in a name and take up less space. Linux tracks all processes started by a user, for example, by the user ID and not the user name. Some utilities translate the user ID to display the user name, but utilities generally examine the /etc/passwd file to match the UID to the name.
The user ID numbers are usually assigned in specific ranges. Most UNIX systems, for example, allocate the numbers from 0 to 99 for machine-specific logins and the user ID numbers from 100 and up for users. Using this model will make your system consistent with others. In the sample /etc/passwd file shown previously, you can see that root has a UID of 0, and the other system-created logins have larger numbers. The login nobody is a special login used for NFS (Network File System) and has a UID of -1, an invalid number. When you assign user ID numbers, assign them sequentially so that the first user is 100, the second 101, and so on.

MCA 209

Software Life Cycle Models
History
The "waterfall model", documented in 1970 by Royce was the first publicly documented life cycle model. The model was developed to help cope with the increasing complexity of aerospace products. The waterfall model followed a documentation driven paradigm. The next revolutionary new look at the development lifecycle was the "spiral model", presented by Boehm in 1985. The spiral model is focused on risk management.
Methods
Life cycle models describe the interrelationships between software development phases. The common life cycle models are:
spiral model
waterfall model
throwaway prototyping model
evolutionary prototyping model
incremental/iterative development
reusable software model
automated software synthesis
Because the life cycle steps are described in very general terms, the models are adaptable and their implementation details will vary among different organizations. The spiral model is the most general. Most life cycle models can in fact be derived as special instances of the spiral model. Organizations may mix and match different life cycle models to develop a model more tailored to their products and capabilities.
Learn
A software life cycle model depicts the significant phases or activities of a software project from conception until the product is retired. It specifies the relationships between project phases, including transition criteria, feedback mechanisms, milestones, baselines, reviews, and deliverables. Typically, a life cycle model addresses the following phases of a software project: requirements phase, design phase, implementation, integration, testing, operations and maintenance. Much of the motivation behind utilizing a life cycle model is to provide structure to avoid the problems of the "undisciplined hacker".
Evaluate
Spiral Model
The spiral model is the most generic of the models. Most life cycle models can be derived as special cases of the spiral model. The spiral uses a risk management approach to software development. Some advantages of the spiral model are:
defers elaboration of low risk software elements
incorporates prototyping as a risk reduction strategy
gives an early focus to reusable software
accommodates life-cycle evolution, growth, and requirement changes
incorporates software quality objectives into the product
focus on early error detection and design flaws
sets completion criteria for each project activity to answer the question: "How much is enough?"
uses identical approaches for development and maintenance
can be used for hardware-software system development
Waterfall Model
The least flexible and most obsolete of the life cycle models. Well suited to projects that has low risk in the areas of user interface and performance requirements, but high risk in budget and schedule predictability and control.
Throwaway Prototyping Model
Useful in "proof of concept" or situations where requirements and user's needs are unclear or poorly specified. The approach is to construct a quick and dirty partial implementation of the system during or before the requirements phase.
Evolutionary Prototyping Model
Use in projects that have low risk in such areas as losing budget, schedule predictability and control, large-system integration problems, or coping with information sclerosis, but high risk in user interface design.
Incremental/iterative Development
The process for constructing several partial deliverables, each having incrementally more functionality.
Automated Software Synthesis
This process relies on tools to transform requirements into operational code. Formal requirements are created and maintained using specification tools. This is an active research area, and practical tools for this approach are yet to be developed.

MCA 203

MCA 203 - Data Base Management System

Brief Summary

LESSON – 1

Database
A collection of related data.

More definitions of File, Record, Data and Information.

Characteristics of DBMS

Self describing nature
Insulation between programs and data and data abstraction
Support of multiple views of data.
Sharing of data and multi-user transaction processing.
etc.

Uses of DBMS
Reducing redundancy and inconsistency
Authorized Access
Multiple user interfaces
Enforcing integrity constraints
Provides backup and recovery etc.

Implications of database approach

Potential for enforcing standards
Reduced application development time
Flexibility
Availability of latest updates.
Economies of scale etc.















LESSON – 2

Architecture
Schema: Description of the database.
Instance: The data in the database stored at a particular moment.
Two-tier
Consists of Client and Server.
ODBC and JDBC used for interaction.

Three-tier
Internal schema
Conceptual schema
External schema

Data Independence

Logical data independence
Capacity to change conceptual schema without changing external schema.

Physical data independence
Capacity to change internal schema without changing conceptual schema.

Database Languages
Data Definition Language
Data Dictionary
Metadata

Data Manipulation Language
Enables user to access or manipulate data.
Procedural DML
Non- Procedural DML
Query Language
A statement requesting retrieval of information.







LESSON – 3

Database Administrator
Responsibilities:
§ Schema definition
§ Authorizing access to the database
Coordinating and monitoring its use.
Maintain database integrity.
Acquiring software & Hardware resources etc.
Database Designers
Responsibilities:
To identify data to be stored.
Choose appropriate structure to represent and store the data
Create a view that meets data & Processing requirements
End Users
Casual users
Naive users
Sophisticated end user
Stand-alone users
System Analysts and Application Programmer
Analysts determine requirements of end users
Programmers implement the specifications in the form of programs.
Data Models
The Entity- Relationship Model
Represents data as set of Entities, Attributes, relationships among them etc.
Relational
Represents data as collection of tables.
Network
Represents data as record types and set type.
Hierarchical
Represents data as tree structure.
Object Oriented
Defines data in terms of objects, their properties and their operations.
LESSON – 4 & 5

ER Model
Data models are tools used in analysis to describe the data requirements and assumptions in the system from a top-down perspective. They also set the stage for the design of databases later on in the SDLC.
There are three basic elements in ER models:
Entity: Basic object represented by the ER model.
§ Attributes are the data we collect about the entities.

§ Relationships provide the structure needed to draw information from multiple entities.

Attributes: Characteristics/ Properties of an entity.
Composite attributes
Single valued
Multivalued
Derived

Entity type
Value sets
Key attributes
Relationships
Cardinality
Degree of relation
Weak entity types

Notations
Rectangle – Entity type
Rhombus – Relationship
Oval – Attribute
etc.
Relationships
§ Binary and Tertiary relations
§ one to one
§ one to many
§ many to many
§ degree binary or ternary etc.



Fig: An example of an ER Diagram































Normalization

First normal form (1NF) sets the very basic rules for an organized database:
Eliminate duplicative columns from the same table.
Create separate tables for each group of related data and identify each row with a unique column or set of columns (the primary key).
Second normal form (2NF) further addresses the concept of removing duplicative data:
Meet all the requirements of the first normal form.
Remove subsets of data that apply to multiple rows of a table and place them in separate tables.
Create relationships between these new tables and their predecessors through the use of foreign keys.
Third normal form (3NF) goes one large step further:
Meet all the requirements of the second normal form.
Remove columns that are not dependent upon the primary key.
Fourth normal form (4NF) has one additional requirement:
Meet all the requirements of the third normal form.
A relation is in 4NF if it has no multi-valued dependencies.




Relational Model

§ A relational database stores all its data inside tables. All operations on data are done on the tables themselves or produces another tables as the result.
§ A table is a set of rows and columns.
§ Each row is a set of columns with only one value for each.
§ All rows from the same table have the same set of columns, although some columns may have NULL values, i.e. the values for that rows was not initialized.
§ A NULL value for a string column is different from an empty string.
§ The rows from a relational table is analogous to a record, and the columns to a field. Here's an example of a table and the SQL statement that creates the table: CREATE TABLE ADDR_BOOK ( NAME char(30), COMPANY char(20), E_MAIL char (25) ) +-------------------+---------------+-----------------------+ NAME COMPANY E_MAIL +===================+===============+=======================+ Nandita IBM nand@ibm.com +-------------------+---------------+-----------------------+ Bill Gates Microsoft bill@microsoft.com +-------------------+---------------+-----------------------+
Two basic operations you can perform on a relational table:
§ The first one is retrieving a subset of its columns.
§ The second is retrieving a subset of its rows.
Operations between two tables:
§ cartesian product of the tables
§ intersection between two tables
§ add one table to another and







Relational Algebra

Relational algebra is a procedural data manipulation language (DML) for the relational model.
§ Standard relational algebra consists of:
a set of operators that map relations to relations
rules for combining those operations into expressions
rules for evaluating such expressions
§ The basic components of relational algebra (RA) expressions are relations
The semantics of RA operations are determined using:
regular "conditional set" expressions e.g. { X condition }
various tuple notations: t[AB] (extract attributes) (x,y,z) (enumerated tuples)
quantifiers, set operations, boolean operators
Notational Conventions
The standard treatment of relational algebra uses Greek symbols. The following notation are used:


Operation

StandardNotation
Selection

expr(Rel)
Projection

A,B,C(Rel)
Join

Rel1 expr Rel2



Selection
The selection operation returns a subset of the tuples in a relation that satisfy a specified condition.
C(r) = Select[C](r) = { t t r C(t) }, where r(R)
The selection condition C is a boolean expression that involves attributes from the relation and constant values.

Operationally:
§ C is evaluated for each tuple in r, with the attribute "variables" in C set to the their values in that tuple
§ any tuple for which C evaluates to true is returned in the result
§ all other tuples are not included in the result
Projection
The projection operation returns a set of tuples containing a subset of the attributes in the original relation.
X(r) = Project[X](r) = { t[X] t r }, where r(R)
The X specifies a subset of the attributes of R.
Operationally:
§ take each tuple in the original relation
§ extract values of the specified subset of the attributes
§ form a new tuple from these values
§ place this new tuple in the result, if not already there
Union
The union operation combines two compatible relations into a single relation via set union of sets of tuples.
r1 r2 = { t t r1 t r2 }, where r1(R), r2(R)

Operationally:
§ make a copy of r1
§ examine each tuple in r2
§ if it's not already in the result, place it there
Intersection
The intersection operation combines two compatible relations into a single relation via set intersection of sets of tuples.
r1 r2 = { t t r1 t r2 }, where r1(R), r2(R)

Operationally:
§ examine each tuple in r1
§ check whether it also appears in r2
§ if it does, place it in the result, otherwise ignore it
Difference
The difference operation finds the set of tuples that exist in one relation but do not occur in a second compatible relation.
r1 - r2 = { t t r1 t r2 }, where r1(R), r2(R)

Operationally:
§ examine each tuple in r1
§ check whether it also appears in r2
§ if it does not, place it in the result, otherwise ignore it
Product
The product (Cartesian product) combines information from two relations pairwise on tuples.
r s = { (t1 : t2) t1 r t2 s }, where r(R), s(S)

Operationally:
§ examine each tuple in r
§ form new tuples by pairing it with each tuple in s
§ place all of these tuples in the result
Natural Join
The natural join operation is a specialised product:
containing only pairs that match on their common attributes
with one of each pair of common attributes eliminated
Consider two relation schemas R(ABC..JKLM) and S(KLMN..XYZ), the natural join of the relations r(R) and s(S) is defined as:
R S = R Join S = { (t1[ABC..J] : t2[K..XYZ]) t1 r t2 s match }
where match = t1[K] = t2[K] t1[L] = t2[L] t1[M] = t2[M]
Join can also be defined in terms of the other relational algebra operations:
r Join s = Project[R S] ( Select[match] ( r s) )


Division
Consider two relation schemas R and S where S R.
The division operation is defined on two instances r(R) and s(S) as:
r / s = r Divide s = { t t r[R-S] satisfy }
where satisfy = ts S ( tr R ( tr[S] = ts tr[R-S] = t ) )

Operationally:
§ consider each subset of tuples in R that match on t[R-S]
§ for this subset of tuples, take the t[S] values from each
§ if this covers all tuples in S, then include t[R-S] in the result

MCA 105

NOTES

MCA-105 Problem Solving Using C

Lesson 1:
A Program is defined as a set of instructions executed sequentially. Any language used to
develop programs is called Programming Language. These languages have been broadly divided into 2 categories High level programming Languages & Low level Programming Languages. High level languages are the languages which are easily understood by human beings but are slow at execution. Whereas the low level languages are difficult to learn but faster at execution. To use the plus points of both these languages C was designed which is called Middle Level Language.

Now to understand some topics of C like (Bitwise operators) something about the binary arithmetic must be known as computer stores everything in binary states either 0 or 1.
This System is known as BINARY SYSTEM. Similarly OCTAL SYSTEM and HEXADECIMAL SYSTEM will be discussed to understand how alphanumeric data is stored in system.

History of C:

The C programming language was devised in the early 1970s as a system implementation language for the nascent Unix operating system.
C came into being in the years 1969-1973, in parallel with the early development of the Unix operating system; the most creative period occurred during 1972. Another spate of changes peaked between 1977 and 1979, when portability of the Unix system was being demonstrated. In the middle of this second period, the first widely available description of the language appeared: The C Programming Language, often called the `white book' or `K&R' [Kernighan 78]. Finally, in the middle 1980s, the language was officially standardized by the ANSI X3J11 committee, which made further changes. Until the early 1980s, although compilers existed for a variety of machine architectures and operating systems, the language was almost exclusively associated with Unix; more recently, its use has spread much more widely, and today it is among the languages most commonly used throughout the computer industry.
BCPL, B, and C all fit firmly in the traditional procedural family typified by Fortran and Algol 60. They are particularly oriented towards system programming, are small and compactly described, and are amenable to translation by simple compilers. They are `close to the machine' in that the abstractions they introduce are readily grounded in the concrete data types and operations supplied by conventional computers, and they rely on library routines for input-output and other interactions with an operating system. With less success, they also use library procedures to specify interesting control constructs such as coroutines and procedure closures.



Lesson 2:
Standardization
By 1982 it was clear that C needed formal standardization. The best approximation to a standard, the first edition of K&R, no longer described the language in actual use; in particular, it mentioned neither the void or enum types. While it foreshadowed the newer approach to structures, only after it was published did the language support assigning them, passing them to and from functions, and associating the names of members firmly with the structure or union containing them. Although compilers distributed by AT&T incorporated these changes, and most of the purveyors of compilers not based on pcc quickly picked up them up, there remained no complete, authoritative description of the language.

Decimal To Binary Conversion









To convert a decimal number to binary, first subtract the largest possible power of two, and keep subtracting the next largest possible power form the remainder, marking 1s in each column where this is possible and 0s where it is not.












Example 1 - (Convert Decimal 44 to Binary)
































Example 2 - (Convert Decimal 15 to Binary)


















































Decimal to Octal Conversion

Octal is base 8. Base 8 is where the only numbers you can use are zero thru to seven. ie: the decimal value for 1 is represented in octal as 1 but the octal value of 8 (Decimal) is shown as 10 the value of 9 (Decimal) is 11 in octal.

Decimal
Octal
Decimal
Octal
Decimal
Octal
1
1
11
13
30
36
2
2
12
14
40
50
3
3
13
15
50
62
4
4
14
16
60
74
5
5
15
17
70
106
6
6
16
20
80
120
7
7
17
21
90
132
8
10
18
22
100
144
9
11
19
23
500
764
10
12
20
24
1000
1750






Lesson 3:

Structure of C Program: We’ll complete the following topics in this section:
C's character set
C's keywords
The general structure of a C program
All C statement must end in a ;
C's Character Set
C does not use, nor requires the use of, every character found on a modern computer keyboard. The only characters required by the C Programming Language are as follows:
A - Z
a -z
0 - 9
space . , : ; ' $ "
# % & ! _ {} [] () < >
+ - / * =
The use of most of this set of characters will be discussed throughout the course.
The form of a C Program
All C programs will consist of at least one function, but it is usual (when your experience grows) to write a C program that comprises several functions. The only function that has to be present is the function called main. For more advanced programs the main function will act as a controlling function calling other functions in their turn to do the dirty work! The main function is the first function that is called when your program executes.
C makes use of only 32 keywords which combine with the formal syntax to the form the C programming language. Note that all keywords are written in lower case - C, like UNIX, uses upper and lowercase text to mean different things. If you are not sure what to use then always use lowercase text in writing your C programs. A keyword may not be used for any other purposes. For example, you cannot have a variable called auto.






Lesson 4:
The layout of C Programs
The general form of a C program is as follows:
pre-processor directivesglobal declarationsmain(){ local variables to function main ; statements associated with function main ;}f1(){ local variables to function 1 ; statements associated with function 1 ;}f2(){ local variables to function f2 ; statements associated with function 2 ;}...etc

Note the use of the bracket set () and {}. () are used in conjunction with function names whereas {} are used as to delimit the C statements that are associated with that function. Also note the semicolon - yes it is there, but you might have missed it! a semicolon (;) is used to terminate C statements. C is a free format language and long statements can be continued, without truncation, onto the next line. The semicolon informs the C compiler that the end of the statement has been reached. Free format also means that you can add as many spaces as you like to improve the look of your programs.










LESSON 5:

Type Declaration Instruction:

This instruction is used to declare the type of variables being used in the program. A variable is a location in RAM (main memory) for temporary storage of intermediate data.
Any variable used in the program must be declared before using it in any statement. The type declaration statement is written at the beginning of main() function.

Ex: int bas;
float rs, grosssal;
char name, code;

These are several subtle variations of the type declaration instruction.

i) While declaring the type of variable we can also initialize it as shown below:

int i=10, j=25;
float a=1.5, b= 1.99+2.4 * 1.45 ;
ii) The order in which we define the variables is sometimes important sometimes not.
For exa:

int i=10,j=20;

is same as
int j=20, i=10;

However,

float a =1.2, b=a+3.1;
is alright, but

float b=a+3.1, a=1.2;

is not.this is because here we are trying to use a even before defining it.

iii) Similarly
int a,b,c,d;
a=b=c=10;
is O.K. but

int a=b=c=d=10;

will not work.( find out why ???)

LESSON 6:

ARITHMETIC INSTRUCTIONS:


A C arithmetic instruction consists of a variable name on the left hand side of = and variable names & constants on the right han side of =. The variables & constants on the right hand side of = are connected by arithmetic operators like + , -, *, /.


Exa:

int ad;
float kot, deta,alpha, beta, gamma;
ad=3200;
koi=0.0056;
.
.
.
.
.
deta= alpha* beta / gamma +3.2 * 2/5;


here

*, /, + are arithmetic operators.
= is assignment operator.
2,5 & 3200 are integer constans.
3.2,0.0056 are real constants.
ad is an integer variable.
Kot, deta, alpha, beta, gamma are real variables.

The variables & constants together are called OPERANDS that are operated upon by the arithmetic operators and the result is assigned using the assignment operator, to the variable on the left hand side.











LESSON 7:


HIERARCHY OF OPEATIONS:


While executing an arithmetic statement, which has two or more operators, we
may have some problems as to how exactly does it get executed. For example, does the expression *x -3 *y correspond to (2x)-(3y) or 2(x-3y)?. To answer these
questions satisfactorily one has to understand the Hierarchy of operations.the priority or precedence in which the operations in a statement are performed is called the Hierarchy of operations.


__________________________________________________________________
PRIORITY OPERATORS DESCRIPTION
__________________________________________________________________

1ST * / % + multiplication, division, modular
division
2nd + - addition , subtraction

3rd = assignment
________________________________________________________________

Few Tips:

a) Within parentheses the same hierarchy is operatie. Also if there are more than
set of parentheses, the operations within the innermost parentheses would be performed first, followed by the operations within the second innermost parentheses & so on.

b) We must always remember to use pair of parentheses. A careless imbalance
of the right and left parentheses is a common error.













LESSON 8:

CONTROL INSTRUCTIONS IN C:

They enable us to specify the order in which the various instructions in a program are to be executed by the computer. They determine the “flow of control” in a program.

4 types of control instructions are:
i) Sequence Control Instruction
ii) Decision Control Instruction
iii) Repetition or Loop Control Instruction
iv) Case Control Instruction
Sequence Control Instruction ensures that the instructions are executed in the same order in which they appear in a program.

Decision Control Instruction allow the computer to take a decision as to which instruction is to be executed next.

Repetition or Loop Control Instruction helps computer to execute a group of statements repeatedly.

Case Control Instruction allows user to take the work of multiple ifs using different cases.

Decision control Structure:

A decision control instruction can be implemented inn C using:
i) The if statement
ii) The if-else statement
iii) The conditional operators


Each of these types with enough examples will be discussed in detail during the class.



LESSON 9:
The if else Statement
This is used to decide whether to do something at a special point, or to decide between two courses of action. The following test decides whether a student has passed an exam with a pass mark of 45 if (result >= 45) printf("Pass\n"); else printf("Fail\n");
It is possible to use the if part without the else. if (temperature < 0) print("Frozen\n");
Each version consists of a test, (this is the bracketed statement following the if). If the test is true then the next statement is obeyed. If is is false then the statement following the else is obeyed if present. After this, the rest of the program continues as normal.If we wish to have more than one statement following the if or the else, they should be grouped together between curly brackets. Such a grouping is called a compound statement or a block. if (result >= 45) { printf("Passed\n"); printf("Congratulations\n") } else { printf("Failed\n"); printf("Good luck in the resits\n"); }
Sometimes we wish to make a multi-way decision based on several conditions. The most general way of doing this is by using the else if variant on the if statement. This works by cascading several comparisons. As soon as one of these gives a true result, the following statement or block is executed, and no further comparisons are performed. In the following example we are awarding grades depending on the exam result. if (result >= 75) printf("Passed: Grade A\n"); else if (result >= 60) printf("Passed: Grade B\n"); else if (result >= 45) printf("Passed: Grade C\n"); else printf("Failed\n");


In this example, all comparisons test a single variable called result. In other cases, each test may involve a different variable or some combination of tests. The same pattern can be used with more or fewer else if's, and the final lone else may be left out. It is up to the programmer to devise the correct structure for each programming problem.










































LESSON 10:

Loops
C gives you a choice of three types of loop, while, do while and for.
· The while loop keeps repeating an action until an associated test returns false. This is useful where the programmer does not know in advance how many times the loop will be traversed.
· The do while loops is similar, but the test occurs after the loop body is executed. This ensures that the loop body is run at least once.
· The for loop is frequently used, usually where the loop will be traversed a fixed number of times. It is very flexible, and novice programmers should take care not to abuse the power it offers.
The while Loop
The while loop repeats a statement until the test at the top proves false.
As an example, here is a function to return the length of a string. Remember that the string is represented as an array of characters terminated by a null character '\0'. int string_length(char string[]) { int i = 0; while (string[i] != '\0') i++; return(i); }
The string is passed to the function as an argument. The size of the array is not specified, the function will work for a string of any size.

The while loop is used to look at the characters in the string one at a time until the null character is found. Then the loop is exited and the index of the null is returned. While the character isn't null, the index is incremented and the test is repeated.












LESSON 11:
The for Loop
The for loop works well where the number of iterations of the loop is known before the loop is entered. The head of the loop consists of three parts separated by semicolons.
· The first is run before the loop is entered. This is usually the initialisation of the loop variable.
· The second is a test, the loop is exited when this returns false.
· The third is a statement to be run every time the loop body is completed. This is usually an increment of the loop counter.
The example is a function which calculates the average of the numbers stored in an array. The function takes the array and the number of elements as arguments. float average(float array[], int count) { float total = 0.0; int i; for(i = 0; i < count; i++) total += array[i]; return(total / count); }
The for loop ensures that the correct number of array elements are added up before calculating the average.
The three statements at the head of a for loop usually do just one thing each, however any of them can be left blank. A blank first or last statement will mean no initialisation or running increment. A blank comparison statement will always be treated as true. This will cause the loop to run indefinitely unless interrupted by some other means. This might be a return or a break statement.
It is also possible to squeeze several statements into the first or third position, separating them with commas. This allows a loop with more than one controlling variable. The example below illustrates the definition of such a loop, with variables hi and lo starting at 100 and 0 respectively and converging.
for (hi = 100, lo = 0; hi >= lo; hi--, lo++)
The for loop is extremely flexible and allows many types of program behaviour to be specified simply and quickly.








LESSON 12:
The do while Loop
This is very similar to the while loop except that the test occurs at the end of the loop body. This guarantees that the loop is executed at least once before continuing. Such a setup is frequently used where data is to be read. The test then verifies the data, and loops back to read again if it was unacceptable. do { printf("Enter 1 for yes, 0 for no :"); scanf("%d", &input_value); } while (input_value != 1 && input_value != 0)
The break Statement
We have already met break in the discussion of the switch statement. It is used to exit from a loop or a switch, control passing to the first statement beyond the loop or a switch.
With loops, break can be used to force an early exit from the loop, or to implement a loop with a test to exit in the middle of the loop body. A break within a loop should always be protected within an if statement which provides the test to control the exit condition.



The continue Statement
This is similar to break but is encountered less frequently. It only works within loops where its effect is to force an immediate jump to the loop control statement.
· In a while loop, jump to the test statement.
· In a do while loop, jump to the test statement.
· In a for loop, jump to the test, and perform the iteration.
Like a break, continue should be protected by an if statement. You are unlikely to use it very often.








LESSON 13:
The switch Statement
This is another form of the multi way decision. It is well structured, but can only be used in certain cases where;
· Only one variable is tested, all branches must depend on the value of that variable. The variable must be an integral type. (int, long, short or char).
· Each possible value of the variable can control a single branch. A final, catch all, default branch may optionally be used to trap all unspecified cases.
Hopefully an example will clarify things. This is a function which converts an integer into a vague description. It is useful where we are only concerned in measuring a quantity when it is quite small. estimate(number) int number; /* Estimate a number as none, one, two, several, many */ { switch(number) { case 0 : printf("None\n"); break; case 1 : printf("One\n"); break; case 2 : printf("Two\n"); break; case 3 : case 4 : case 5 : printf("Several\n"); break; default : printf("Many\n"); break; }}
Each interesting case is listed with a corresponding action. The break statement prevents any further statements from being executed by leaving the switch. Since case 3 and case 4 have no following break, they continue on allowing the same action for several values of number.
Both if and switch constructs allow the programmer to make a selection from a number of possible actions.
The other main type of control statement is the loop. Loops allow a statement, or block of statements, to be repeated. Computers are very good at repeating simple tasks many times, the loop is C's way of achieving this.




LESSON 14:
The goto Statement
C has a goto statement which permits unstructured jumps to be made. Its use is not recommended, so we'll not teach it here. Consult your textbook for details of its use.


SOME MORE KNOWLEDGE ABOUT C:
ANSI C
The American National Standards Institute defined a standard for C, eliminating much uncertainty about the exact syntax of the language. This newcomer, called ANSI C, proclaims itself the standard version of the language. As such it will inevitably overtake, and eventually replace common C.
ANSI C does incorporate a few improvements over the old common C. The main difference is in the grammar of the language. The form of function declarations has been changed making them rather more like Pascal procedures.
This course introduces ANSI C since it is supported by the SUN workstation compilers. Most C programming texts are now available in ANSI editions.

A Very Simple Program
This program which will print out the message This is a C program #include main() { printf("This is a C program\n"); }
Though the program is very simple, a few points are worthy of note.
Every C program contains a function called main. This is the start point of the program.
#include allows the program to interact with the screen, keyboard and filesystem of your computer. You will find it at the beginning of almost every C program.
main() declares the start of the function, while the two curly brackets show the start and finish of the function. Curly brackets in C are used to group statements together as in a function, or in the body of a loop. Such a grouping is known as a compound statement or a block.




printf("This is a C program\n");
prints the words on the screen. The text to be printed is enclosed in double quotes. The \n at the end of the text tells the program to print a newline as part of the output.

Most C programs are in lower case letters. You will usually find upper case letters used in preprocessor definitions (which will be discussed later) or inside quotes as parts of character strings. C is case sensitive, that is, it recognises a lower case letter and it's upper case equivalent as being different.






































LESSON 15:

In principle arrays in C are similar to those found in other languages. As we shall shortly see arrays are defined slightly differently and there are many subtle differences due the close link between array and pointers. We will look more closely at the link between pointer and arrays in notes ahead.

Let us first look at how we define arrays in C: int listofnumbers[50];

BEWARE: In C Array subscripts start at 0 and end one less than the array size. For example, in the above case valid subscripts range from 0 to 49. This is a BIG difference between C and other languages and does require a bit of practice to get in the right frame of mind.

Elements can be accessed in the following ways:- thirdnumber=listofnumbers[2]; listofnumbers[5]=100;


An array is a collection of variables of the same type which are referenced by a common name. A specific element in an array is referenced by an index. The most common array in C is the string, which is simply an array of characters terminated by a null.
In C, arrays and pointers are closely related; a discussion of one usually refers to the other.
C has no bounds checking on arrays.
So the general form for declaring a single-dimension array is: type var_name[size];
In C, all arrays have zero as the index of their first element. Therefore a declaration of char p[10]; declares a ten-element array (p[0] through p[9]).










LESSON 16:
Generating a Pointer to an Array
A pointer to the first element in an array may be generated by simply specifying the array name, without any index. For example, given: int sample[10];
a pointer to the first element may be generated by simply using the name sample. For example, the following code fragment assigns p the address of the first element of sample: int *p; int sample[10]; p = sample;
The address of the first element may also be specified using the & operator. For example, sample and &sample[0] produce the same result. The former is usually used.
Strings
A string is actually an array of characters. Because strings are terminated by a null ('\0'), character arrays must be declared with one extra element (to hold the null).
Although C does not have a string data type, it allows string constants. For example, "hello there" is a string constant.
C supports a wide range of string manipulation functions, including:
Function
Description
strcpy(s1,s2)
Copies s2 into s1.
strcat(s1,s2)
Concatenates s2 to s1.
strlen(s1)
Returns the length of s1.
strcmp(s1,s2)
Returns 0 (false) if s1 and s2 are the same.Returns less than 0 if s1&lts2Returns greater than 0 if s1>s2
strchr(s1,ch)
Returns pointer to first occurrence ch in s1.
strstr(s1,s2)
Returns pointer to first occurrence s2 in s1.
Since strcmp() returns false if the strings are equal, it is best to use the ! operator to reverse the condition if the test is for equality.




LESSON 17:
Two-Dimensional Arrays

In C, a two-dimensional array is declared as shown in the following example: int d[10][20];
Two-dimensional arrays are stored in a row-column matrix. The first index indicates the row. The row index can be thought of as a &quotpointer"to the correct row.

When a two-dimensional array is used as an argument to a function, only a pointer to the first element is passed. However, the receiving function must define at least the length of the second dimension, e.g.:
function(int x[][20]

Arrays of Strings
Arrays of strings are created using a two-dimensional array. The left index determines the number of strings. Each string is accessed using only the left index (eg, gets(array[2] accesses the third string).
Multi-Dimensional Arrays
C allows arrays of more than two dimensions, the exact limit depending on the individual compiler.
In C, pointers and arrays are closely related. As previously stated, an array name without an index is a pointer to the first element. For example, given the array char my_array[10];, my_array and &my_array[0] are identical.
Conversely, any pointer variable may be indexed as if it were declared as an array. For example, in this program fragment: int *p, i[10]; p = i; p[5] = 100; // assignment using index (p+5) = 100 // assignment using pointer arithmetic
both assignments achieve the same thing.




LESSON 18:

Array Initialization
Arrays may be initialized at the time of declaration. The following example initializes a ten-element integer array: int i[10] = { 1,2,3,4,5,6,7,8,9,10 };
Character arrays which hold strings allow a shorthand initialization, e.g.: char str[9] = "I like C";
which is the same as: char str[9] = { 'I',' ','l','i','k','e',' ','C','\0' };
When the string constant method is used, the compiler automatically supplies the null terminator.
Multi-dimensional arrays are initialized in the same way as single-dimension arrays, e.g.: int sgrs[6][2] = { 1,1, 2,4, 3,9, 4,16, 5,25 6,36 };
Unsized Array Initializations
If unsized arrays are declared, the C compiler automatically creates an array big enough to hold all the initializers. This is called an unsized array. Example declaration/initializations are as follows: char e1[] = "read error\n"; char e2[] = "write error\n"; int sgrs[][2] = { 1,1, 2,4, 3,9 4,16, };




LESSON 19:
Pointers :
Pointer are a fundamental part of C. If you cannot use pointers
properly then you have basically lost all the power and flexibility that C allows. The secret to C is in its use of pointers.
C uses pointers a lot. Why?:
· It is the only way to express some computations.
· It produces compact and efficient code.
· It provides a very powerful tool.
C uses pointers explicitly with:
· Arrays,
· Structures,
· Functions.
NOTE: Pointers are perhaps the most difficult part of C to understand. C's implementation is slightly different DIFFERENT from other languages.
What is a Pointer?
A pointer is a variable which contains the address in memory of another variable. We can have a pointer to any variable type.
The unary or monadic operator & gives the ``address of a variable''.
The indirection or dereference operator * gives the ``contents of an object pointed to by a pointer''.
To declare a pointer to a variable do:
int *pointer;
NOTE: We must associate a pointer to a particular type: You can't assign the address of a short int to a long int, for instance.





LESSON 20:

(Pointers Contd..)
Consider the effect of the following code:
int x = 1, y = 2; int *ip; ip = &x; y = *ip;
x = ip;
*ip = 3;

It is worth considering what is going on at the machine level in memory to fully understand how pointer work. Consider Fig. 9.1. Assume for the sake of this discussion that variable x resides at memory location 100, y at 200 and ip at 1000. Note A pointer is a variable and thus its values need to be stored somewhere. It is the nature of the pointers value that is new.

Fig. 9.1 Pointer, Variables and Memory Now the assignments x = 1 and y = 2 obviously load these values into the variables. ip is declared to be a pointer to an integer and is assigned to the address of x (&x). So it gets loaded with the value 100.






IMPORTANT: When a pointer is declared it does not point anywhere. You must set it to point somewhere before you use it.
So ... int *ip; *ip = 100;
will generate an error (program crash!!).
The correct use is: int *ip; int x; ip = &x; *ip = 100;




























LESSON 21:
Pointers and Arrays
Pointers and arrays are very closely linked in C.
Hint: think of array elements arranged in consecutive memory locations.
Consider the following: int a[10], x; int *pa; pa = &a[0]; /* pa pointer to address of a[0] */ x = *pa; /* x = contents of pa (a[0] in this case) */

Fig. 9.3 Arrays and Pointers

To get somewhere in the array (Fig. 9.3) using a pointer we could do:
pa + i a[i]

WARNING: There is no bound checking of arrays and pointers so you can easily go beyond array memory and overwrite other things.

C however is much more subtle in its link between arrays and pointers.
For example we can just type
pa = a;
instead of
pa = &a[0]
and
a[i] can be written as *(a + i). i.e. &a[i] a + i.
We also express pointer addressing like this:
pa[i] *(pa + i).

However pointers and arrays are different:
· A pointer is a variable. We can do pa = a and pa++.
· An Array is not a variable. a = pa and a++ ARE ILLEGAL.


LESSON 22:

(Pointers and Arrays in more detail)
pointer is a variable suitable for keeping memory addresses of other variables, the values you assign to a pointer are memory addresses of other variables (or other pointers). How useful are pointers for scientific programming? Probably much less thanC fans think, few algorithms used in scientific require pointers. It is well-known that having unrestricted pointers in a programming language makes it difficult for the compiler to generate efficient code. C pointers are characterized by their value and data-type. The value is the address of the memory location the pointer points to, the type determines how the pointer will be incremented/decremented in pointer (or subscript) arithmetic (see below). Arrays in C and the array equation ---------------------------------- We will use 2D arrays in the following text instead of general N-dimensional arrays, they can illustrate the subtle points involved with using arrays and pointers in C, and the arithmetic will be more manageable. A 2D array in C is treated as a 1D array whose elements are 1D arrays (the rows). For example, a 4x3 array of T (where "T" is some data type) may be declared by: "T mat[4][3]", and described by the following scheme: +-----+-----+-----+ mat == mat[0] ---> a00 a01 a02 +-----+-----+-----+ +-----+-----+-----+ mat[1] ---> a10 a11 a12 +-----+-----+-----+ +-----+-----+-----+ mat[2] ---> a20 a21 a22 +-----+-----+-----+ +-----+-----+-----+ mat[3] ---> a30 a31 a32 +-----+-----+-----+
LESSON 23:

(Pointers and Arrays in more detail) (Contd.) The array elements are stored in memory row after row, so the array equation for element "mat[m][n]" of type T is: address(mat[i][j]) = address(mat[0][0]) + (i * n + j) * size(T) address(mat[i][j]) = address(mat[0][0]) + i * n * size(T) + j * size(T) address(mat[i][j]) = address(mat[0][0]) + i * size(row of T) + j * size(T) A few remarks: 1) The array equation is important, it is the connection between the abstract data-type and its implementation. In Fortran (and other languages) it is
"hidden" from the programmer, the compiler automatically "plants" the necessary code whenever an array reference is made. 2) For higher-dimensional arrays the equation gets more and more complicated. In some programming languages an arbitrary limit on the dimension is imposed, e.g. Fortran arrays can be 7D at most. 2) Note that it's more efficient to compute the array equation "iteratively" - not using the distributive law to eliminate the parentheses (just count the arithmetical operations in the first two versions of the array equation above). The K&R method (see below) works iteratively. It reminds one of Horner's Rule for computing a polynomial iterativly, e.g. a * x**2 + b * x + c = (a * x + b) * x + c computing the powers of x is eliminated in this way. 4) The number of rows doesn't enter into the array equation, you don't need it to compute the address of an element. That is the reason you don't have to specify the first dimension in a routine that is being passed a
2Darray, just like in Fortran's assumed-size arrays.
LESSON 24:

(Pointers and Arrays in more detail) (Contd.) The K&R method of reducing arrays to pointers --------------------------------------------- K&R tried to create a unified treatment of arrays and pointers, one that would expose rather than hide the array equation in the compiler's code. They found an elegant solution, albeit a bit complicated. The "ugly" array equation is replaced in their formulation by four rules: 1) An array of dimension N is a 1D array with elements that are arrays of dimension N-1. 2) Pointer addition is defined by: ptr # n = ptr + n * size(type-pointed-into) "#" denotes here pointer addition to avoid confusion with ordinary addition. The function "size()" returns object's sizes. 3) The famous "decay convention": an array is treated as a pointer that points to the first element of the array. The decay convention shouldn't be applied more than once to the same object. 4) Taking a subscript with value i is equivalent to the operation: "pointer-add
i and then type-dereference the sum", i.e. xxx[i] = *(xxx # i) When rule #4 + rule #3 are applied recursively (this is the case of a multi- dimensional array), only the data type is dereferenced and not the pointer's value, except on the last step.
LESSON 25:

(Pointers and Arrays in more detail) (Contd.) K&R rules imply the array equation ---------------------------------- We will show now that the array equation is a consequence of the above rules (applied recursively) in the case of a 2D array: mat[i] = *(mat # i) (rule 4) mat[i][j] = *(*(mat # i) # j) (rule 4) "mat" is clearly a "2D array of T" and decays by rule #3 into a "pointer to a row of T". So we get the first two terms of the array equation. mat[i][j] = *(*(mat + i * sizeof(row)) # j) ^^^^^^^^^^^^^^^^^^^^^ Pointer to row of T Dereferencing the type of "(mat # i)" we get a "row of T". mat[i][j] = *((mat + i * sizeof(row)) # j) ^^^^^^^^^^^^^^^^^^^^^^^ Row of T We have now one pointer addition left, using again the "decay convention", the 1D array "row of T" becomes a pointer to its first element, i.e. "pointer to T". We perform the pointer addition, and get the third term of the array equation: mat[i][j] = *(mat + i * sizeof(row) + j * sizeof(T)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Pointer to T address(mat[i][j]) = mat + i * sizeof(row) + j * sizeof(T) Remember that "mat" actually points to the first element of the array, so we can write: address(mat[i][j]) = address(mat[0][0]) + i * sizeof(row) + j * sizeof(T) This is exactly the array equation. QED
LESSON 26:

(Pointers and Arrays in more detail) (Contd.) Why a double pointer can't be used as a 2D array? ------------------------------------------------- This is a good example, although the compiler may not complain, it is wrong to declare: "int **mat" and then use "mat" as a 2D array. These are two very different data-types and using them you access different locations in memory.
On a good machine (e.g. VAX/VMS) this mistake aborts the program with a "memory access violation" error. This mistake is common because it is easy to forget that the decay convention mustn't be applied recursively (more than once) to the same array, so a 2D array is NOT equivalent to a double pointer. A "pointer to pointer of T" can't serve as a "2D array of T". The 2D array is "equivalent" to a "pointer to row of T", and this is very different from "pointer to pointer of T". When a double pointer that points to the first element of an array, is used with subscript notation "ptr[0][0]", it is fully dereferenced two times (see rule #5). After two full dereferencings the resulting object will have an address equal to whatever value was found INSIDE the first element of the array. Since the first element contains our data, we would have wild memory accesses. We could take care of the extra dereferencing by having an intermediary "pointer to T": type mat[m][n], *ptr1, **ptr2; ptr2 = &ptr1; ptr1 = (type *)mat; but that wouldn't work either, the information on the array "width" (n), is lost, and we would get right only the first row, then we will have again wild memory accesses. A possible way to make a double pointer work with a 2D array notation is having an auxiliary array of pointers, each of them points to a row of the original matrix. type mat[m][n], *aux[m], **ptr2; ptr2 = (type **)aux; for (i = 0 ; i < m ; i++) aux[i] = (type *)mat + i * n;
LESSON 27:

(Pointers and Arrays in more detail) (Contd.) An example program: include include main() { long mat[5][5], **ptr; mat[0][0] = 3; ptr = (long **)mat; printf(" mat %p \n", mat); printf(" ptr %p \n", ptr); printf(" mat[0][0] %d \n", mat[0][0]); printf(" &mat[0][0] %p \n", &mat[0][0]); printf(" &ptr[0][0] %p \n", &ptr[0][0]); return; } The output on VAX/VMS is: mat 7FDF6310 ptr 7FDF6310 mat[0][0] 3 &mat[0][0] 7FDF6310 &ptr[0][0] 3 We can see that "mat[0][0]" and "ptr[0][0]" are different objects (they have different addresses), although "mat" and "ptr" have the same value.







LESSON 28:
Functions in C
Almost all programming languages have some equivalent of the function. You may have met them under the alternative names subroutine or procedure.
Some languages distinguish between functions which return variables and those which don't. C assumes that every function will return a value. If the programmer wants a return value, this is achieved using the return statement. If no return value is required, none should be used when calling the function.
Here is a function which raises a double to the power of an unsigned, and returns the result. double power(double val, unsigned pow) { double ret_val = 1.0; unsigned i; for(i = 0; i < pow; i++) ret_val *= val; return(ret_val); }
The function follows a simple algorithm, multiplying the value by itself pow times. A for loop is used to control the number of multiplications, and variable ret_val stores the value to be returned.
Let us examine the details of this function.
double power(double val, unsigned pow) This line begins the function definition. It tells us the type of the return value, the name of the function, and a list of arguments used by the function. The arguments and their types are enclosed in brackets, each pair separated by commas.
The body of the function is bounded by a set of curly brackets. Any variables declared here will be treated as local unless specifically declared as static or extern types.
return(ret_val); On reaching a return statement, control of the program returns to the calling function. The bracketed value is the value which is returned from the function. If the final closing curly bracket is reached before any return value, then the function will return automatically, any return value will then be meaningless.



The example function can be called by a line in another function which looks like this result = power(val, pow);
This calls the function power assigning the return value to variable result.
Here is an example of a function which does not return a value. void error_line(int line) { fprintf(stderr, "Error in input data: line %d\n", line); }
The definition uses type void which is optional. It shows that no return value is used. Otherwise the function is much the same as the previous example, except that there is no return statement. Some void type functions might use return, but only to force an early exit from the function, and not to return any value. This is rather like using break to jump out of a loop.

























LESSON 29:

Scope of Function Variables
Only a limited amount of information is available within each function. Variables declared within the calling function can't be accessed unless they are passed to the called function as arguments. The only other contact a function might have with the outside world is through global variables.
Local variables are declared within a function. They are created anew each time the function is called, and destroyed on return from the function. Values passed to the function as arguments can also be treated like local variables.
Static variables are slightly different, they don't die on return from the function. Instead their last value is retained, and it becomes available when the function is called again.
Global variables don't die on return from a function. Their value is retained, and is available to any other function which accesses them.
Modifying Function Arguments
Some functions work by modifying the values of their arguments. This may be done to pass more than one value back to the calling routine, or because the return value is already being used in some way. C requires special arrangements for arguments whose values will be changed.
You can treat the arguments of a function as variables, however direct manipulation of these arguments won't change the values of the arguments in the calling function. The value passed to the function is a copy of the calling value. This value is stored like a local variable, it disappears on return from the function.
There is a way to change the values of variables declared outside the function. It is done by passing the addresses of variables to the function. These addresses, or pointers, behave a bit like integer types, except that only a limited number of arithmetic operators can be applied to them. They are declared differently to normal types, and we are rarely interested in the value of a pointer. It is what lies at the address which the pointer references which interests us.
To get back to our original function, we pass it the address of a variable whose value we wish to change. The function must now be written to use the value at that address (or at the end of the pointer). On return from the function, the desired value will have changed. We manipulate the actual value using a copy of the pointer.









LESSON 30:
Function Prototypes:
A function declaration precedes the function definition and specifies the name, return type, storage class, and other attributes of a function. To be a prototype, the function declaration must also establish types and identifiers for the functions arguments.
The prototype has the same form as the function definition, except that it is terminated by a semicolon immediately following the closing parenthesis and therefore has no body. In either case, the return type must agree with the return type specified in the function definition.
Function prototypes have the following important uses:
i) They establish the return type for functions that return types other than int. Although functions that return int values do not require prototypes, prototypes are recommended.
ii) Without complete prototypes, standard conversions are made, but no attempt is made to check the type or number of arguments with the number of parameters.
iii) Prototypes are used to initialize pointers to functions before those functions are defined.
iv) The parameter list is used for checking the correspondence of arguments in the function call with the parameters in the function definition.
The converted type of each parameter determines the interpretation of the arguments that the function call places on the stack. A type mismatch between an argument and a parameter may cause the arguments on the stack to be misinterpreted. For example, on a 16-bit computer, if a 16-bit pointer is passed as an argument, then declared as a long parameter, the first 32 bits on the stack are interpreted as a long parameter. This error creates problems not only with the long parameter, but with any parameters that follow it. You can detect errors of this kind by declaring complete function prototypes for all functions.
A prototype establishes the attributes of a function so that calls to the function that precede its definition (or occur in other source files) can be checked for argument-type and return-type mismatches.



LESSON 31:
Pointer and Functions
Let us now examine the close relationship between pointers and C's other major parts. We will start with functions.
When C passes arguments to functions it passes them by value.

There are many cases when we may want to alter a passed argument in the function and receive the new value back once to function has finished. Other languages do this (e.g. var parameters in PASCAL). C uses pointers explicitly to do this. Other languages mask the fact that pointers also underpin the implementation of this.

The best way to study this is to look at an example where we must be able to receive changed parameters.

Let us try and write a function to swap variables around?

The usual function call:
swap(a, b) WON'T WORK.

Pointers provide the solution: Pass the address of the variables to the functions and access address of function.

Thus our function call in our program would look like this:
swap(&a, &b)

The Code to swap is fairly straightforward: void swap(int *px, int *py) { int temp; temp = *px; /* contents of pointer */ *px = *py; *py = temp; }

LESSON 32:
Common Pointer Pitfalls :
Here we will highlight two common mistakes made with pointers.
Not assigning a pointer to memory address before using it int *x; *x = 100; We need a physical location say: int y; x = &y; *x = 100;
This may be hard to spot. NO COMPILER ERROR. Also x could some random
address at initialisation.
Illegal indirection
Suppose we have a function malloc() which tries to allocate memory dynamically (at run time) and returns a pointer to block of memory requested if successful or a NULL pointer otherwise.

char *malloc() -- a standard library function (see later).
Let us have a pointer: char *p;
Consider:
*p = (char *) malloc(100); /* request 100 bytes of memory */
*p = `y';
There is mistake above. What is it?
No * in
*p = (char *) malloc(100);
Malloc returns a pointer. Also p does not point to any address.
The correct code should be:
p = (char *) malloc(100);

If code rectified one problem is if no memory is available and p is NULL. Therefore we can't do: *p = `y';.






A good C program would check for this: p = (char *) malloc(100); if ( p == NULL) { printf(``Error: Out of Memory

n''); exit(1); } *p = `y';
Exercise 1.
Write a program to find the number of times that a given word(i.e. a short string) occurs in a sentence (i.e. a long string!).
Read data from standard input. The first line is a single word, which is followed by general text on the second line. Read both up to a newline character, and insert a terminating null before processing.
Typical output should be: The word is "the". The sentence is "the cat sat on the mat". The word occurs 2 times.
Exercise 2.

Write a program that takes three variable (a, b, b) in as separate parameters and rotates the values stored so that value a goes to be, b, to c and c to a.
LESSON 33:
The C Preprocessor
The C preprocessor is a tool which filters your source code before it is compiled. The preprocessor allows constants to be named using the #define notation. The preprocessor provides several other facilities which will be described here. It is particularly useful for selecting machine dependent pieces of code for different computer types, allowing a single program to be compiled and run on several different computers.
The C preprocessor isn't restricted to use with C programs, and programmers who use other languages may also find it useful, however it is tuned to recognise features of the C language like comments and strings, so its use may be restricted in other circu mstances.
The preprocessor is called cpp, however it is called automatically by the compiler so you will not need to call it while programming in C.
Using #define to Implement Constants
We have already met this facility, in its simplest form it allows us to define textual substitutions as follows. #define MAXSIZE 256 This will lead to the value 256 being substituted for each occurrence of the word MAXSIZE in the file.
Using #define to Create Functional Macros

#define can also be given arguments which are used in its replacement. The definitions are then called macros. Macros work rather like functions, but with the following minor differences.
Since macros are implemented as a textual substitution, there is no effect on program performance (as with functions).
Recursive macros are generally not a good idea.
Macros don't care about the type of their arguments. Hence macros are a good choice where we might want to operate on reals, integers or a mixture of the two. Programmers sometimes call such type flexibility polymorphism.
Macros are generally fairly small.
Macros are full of traps for the unwary programmer. In particular the textual substitution means that arithmetic expressions are liable to be corrupted by the order of evaluation rules.
Here is an example of a macro which won't work. #define DOUBLE(x) x+x
Now if we have a statement a = DOUBLE(b) * c;
This will be expanded to a = b+b * c;
And since * has a higher priority than +, the compiler will treat it as. a = b + (b * c);
The problem can be solved using a more robust definition of DOUBLE #define DOUBLE(x) (x+x)
Here the brackets around the definition force the expression to be evaluated before any surrounding operators are applied. This should make the macro more reliable.
In general it is better to write a C function than risk using a macro. LESSON 34:
Reading in Other Files using #include

The preprocessor directive #include is an instruction to read in the entire contents of another file at that point. This is generally used to read in header files for library functions. Header files contain details of functions and types used within the library. They must be included before the program can make use of the library functions.
Library header file names are enclosed in angle brackets, < >. These tell the preprocessor to look for the header file in the standard location for library definitions. This is /usr/include for most UNIX systems.
For example #include Another use for #include for the programmer is where multi-file programs are being written. Certain information is required at the beginning of each program file. This can be put into a file called globals.h and included in each program file. Local header file names are usually enclosed by double quotes, " ". It is conventional to give header files a name which ends in .h to distinguish them from other types of file.
Conditional selection of code using #ifdef

The preprocessor has a conditional statement similar to C's if else. It can be used to selectively include statements in a program. This is often used where two different computer types implement a feature in different ways. It allows the programmer to produce a program which will run on either type.

The keywords for conditional selection are; #ifdef, #else and #endif.

#ifdef
takes a name as an argument, and returns true if the the name has a current definition. The name may be defined using a #define, the -d option of the compiler, or certain names which are automatically defined by the UNIX environment.
#else
is optional and ends the block beginning with #ifdef. It is used to create a 2 way optional selection.
#endif
ends the block started by #ifdef or #else.
Where the #ifdef is true, statements between it and a following #else or #endif are included in the program. Where it is false, and there is a following #else, statements between the #else and the following #endif are included.

MCA 101

MCA 101 Introduction to Information Technology

Lesson 1

In this we will talk about how versatile this tool computer is, why is it so powerful and useful, what are its limitations.
The word computer comes from “compute” which means calculate. So it is taken as calculating device that can perform different operations.
It can be define as a device that operates upon data. Data can be anything like records of student. A computer can store, process and retrieve data as and when desired. That’s why also referred as data processor. The activity of processing data using a computer called data processing.

Data processing consist of three activites
- Capturing the input data
- Manipulating the data
- Managing the output result
Information is data arranged in an order and form that is useful to the people who receive it.


Characteristics of computer :
Automatic : Computers are automatic machines because once started on a job , they carry on until the job is finished.
Speed : It can perform in a few seconds the amount of work that a human does in a year. Unit of speed is microseconds , nanoseconds etc.
Accuracy : The accuracy of computer is consistently high.
Diligence: A computer is free from monotony, tiredness, lack of concentration etc.
Versatility: A computer is capable of performing almost anytask.
Power of Remembering : It can store large amount of data and can be recalled at any point of time.
No I.Q.: It performs as human instruct to system.
No Feeling: Computer are devoid of emotions













MCA 101 Introduction to Information Technology

Lesson 2

Introduction

The history of computer development is often referred to in reference to the different generations of computing devices. Each generation of computer is characterized by a major technological development that fundamentally changed the way computers operate, resulting in increasingly smaller, cheaper, more powerful and more efficient and reliable devices.
The first multi-purpose, i.e. programmable, computing device was probably Charles Babbage's Difference Engine, which was begun in 1823 but never completed. A more ambitious machine was the Analytical Engine. It was designed in 1842, but unfortunately it also was only partially completed by Babbage.

First Generation - 1940-1956: Vacuum Tubes
The first computers used vacuum tubes for circuitry and magnetic drums for memory, and were often enormous, taking up entire rooms. They were very expensive to operate and in addition to using a great deal of electricity, generated a lot of heat, which was often the cause of malfunctions. First generation computers relied on machine language to perform operations, and they could only solve one problem at a time. Input was based on punched cards and paper tape, and output was displayed on printouts.
The UNIVAC and ENIAC computers are examples of first-generation computing devices. The UNIVAC was the first commercial computer delivered to a business client, the U.S. Census Bureau in 1951.
Second Generation - 1956-1963: Transistors
Transistors replaced vacuum tubes and ushered in the second generation of computers. The transistor was invented in 1947 but did not see widespread use in computers until the late 50s. The transistor was far superior to the vacuum tube, allowing computers to become smaller, faster, cheaper, more energy-efficient and more reliable than their first-generation predecessors. Though the transistor still generated a great deal of heat that subjected the computer to damage, it was a vast improvement over the vacuum tube. Second-generation computers still relied on punched cards for input and printouts for output.
Second-generation computers moved from cryptic binary machine language to symbolic, or assembly, languages, which allowed programmers to specify instructions in words. High-level programming languages were also being developed at this time, such as early versions of COBOL and FORTRAN. These were also the first computers that stored their instructions in their memory, which moved from a magnetic drum to magnetic core technology.
The first computers of this generation were developed for the atomic energy industry.

Lesson 3
Third Generation - 1964-1971: Integrated Circuits
The development of the integrated circuit was the hallmark of the third generation of computers. Transistors were miniaturized and placed on silicon chips, called semiconductors, which drastically increased the speed and efficiency of computers.
Instead of punched cards and printouts, users interacted with third generation computers through keyboards and monitors and interfaced with an operating system, which allowed the device to run many different applications at one time with a central program that monitored the memory. Computers for the first time became accessible to a mass audience because they were smaller and cheaper than their predecessors.
Fourth Generation - 1971-Present: Microprocessors
The microprocessor brought the fourth generation of computers, as thousands of integrated circuits were built onto a single silicon chip. What in the first generation filled an entire room could now fit in the palm of the hand. The Intel 4004 chip, developed in 1971, located all the components of the computer - from the central processing unit and memory to input/output controls - on a single chip.
In 1981 IBM introduced its first computer for the home user, and in 1984 Apple introduced the Macintosh. Microprocessors also moved out of the realm of desktop computers and into many areas of life as more and more everyday products began to use microprocessors.
As these small computers became more powerful, they could be linked together to form networks, which eventually led to the development of the Internet. Fourth generation computers also saw the development of GUIs, the mouse and handheld devices.
Lesson 4

Fifth Generation - Present and Beyond: Artificial Intelligence
Fifth generation computing devices, based on artificial intelligence, are still in development, though there are some applications, such as voice recognition, that are being used today. The use of parallel processing and superconductors is helping to make artificial intelligence a reality. Quantum computation and molecular and nanotechnology will radically change the face of computers in years to come. The goal of fifth-generation computing is to develop devices that respond to natural language input and are capable of learning and self-organization.

Monday, January 12, 2009

snagavenkata@gmail.com

Advanced Software Engineering was founded in 1995 by several software developers who believed that the key to improving programmer productivity is to have good reusable software components. Since its foundation, Advanced Software Engineering has been developing software components and libraries for major vendors and corporations. Our areas of expertise are system and network management, network security, and web based user interface. At first, ASE was developing software on a project basis. Then in 2001, ASE decided to offer its software components and libraries as off-the-shelf products available to the public. ChartDirector is the first software component that ASE converted to become off-the-shelf software. This product turns out to be extremely successful, and has been ported to many platforms and programming systems. ASE is now focusing entirely on the continual development, support and marketing of ChartDirector.

Sunday, January 4, 2009

shortcut keys

Press
To
CTRL+C
Copy.
CTRL+X
Cut.
CTRL+V
Paste.
CTRL+Z
Undo.
DELETE
Delete.
SHIFT+DELETE
Delete selected item permanently without placing the item in the Recycle Bin.
CTRL while dragging an item
Copy selected item.
CTRL+SHIFT while dragging an item
Create shortcut to selected item.
F2
Rename selected item.
CTRL+RIGHT ARROW
Move the insertion point to the beginning of the next word.
CTRL+LEFT ARROW
Move the insertion point to the beginning of the previous word.
CTRL+DOWN ARROW
Move the insertion point to the beginning of the next paragraph.
CTRL+UP ARROW
Move the insertion point to the beginning of the previous paragraph.
CTRL+SHIFT with any of the arrow keys
Highlight a block of text.
SHIFT with any of the arrow keys
Select more than one item in a window or on the desktop, or select text within a document.
CTRL+A
Select all.
F3
Search for a file or folder.
ALT+ENTER
View properties for the selected item.
ALT+F4
Close the active item, or quit the active program.
ALT+Enter
Displays the properties of the selected object.
ALT+SPACEBAR
Opens the shortcut menu for the active window.
CTRL+F4
Close the active document in programs that allow you to have multiple documents open simultaneously.
ALT+TAB
Switch between open items.
ALT+ESC
Cycle through items in the order they were opened.
F6
Cycle through screen elements in a window or on the desktop.
F4
Display the Address bar list in My Computer or Windows Explorer.
SHIFT+F10
Display the shortcut menu for the selected item.
ALT+SPACEBAR
Display the System menu for the active window.
CTRL+ESC
Display the Start menu.
ALT+Underlined letter in a menu name
Display the corresponding menu.
Underlined letter in a command name on an open menu
Carry out the corresponding command.
F10
Activate the menu bar in the active program.
RIGHT ARROW
Open the next menu to the right, or open a submenu.
LEFT ARROW
Open the next menu to the left, or close a submenu.
F5
Refresh the active window.
BACKSPACE
View the folder one level up in My Computer or Windows Explorer.
ESC
Cancel the current task.
SHIFT when you insert a CD into the CD-ROM drive
Prevent the CD from automatically playing.



Press
To
CTRL+TAB
Move forward through tabs.
CTRL+SHIFT+TAB
Move backward through tabs.
TAB
Move forward through options.
SHIFT+TAB
Move backward through options.
ALT+Underlined letter
Carry out the corresponding command or select the corresponding option.
ENTER
Carry out the command for the active option or button.
SPACEBAR
Select or clear the check box if the active option is a check box.
Arrow keys
Select a button if the active option is a group of option buttons.
F1
Display Help.
F4
Display the items in the active list.
BACKSPACE
Open a folder one level up if a folder is selected in the Save As or Open dialog box.


Press
To
Display or hide the Start menu.
+BREAK
Display the System Properties dialog box.
+D
Show the desktop.
+M
Minimize all windows.
+Shift+M
Restores minimized windows.
+E
Open My Computer.
+F
Search for a file or folder.
CTRL+ +F
Search for computers.
+F1
Display Windows Help.
+ L
Lock your computer if you are connected to a network domain, or switch users if you are not connected to a network domain.
+R
Open the Run dialog box.
Display the shortcut menu for the selected item.
+U
Open Utility Manager.


Press
To
Right SHIFT for eight seconds
Switch FilterKeys on and off.
Left ALT +left SHIFT +PRINT SCREEN
Switch High Contrast on and off.
Left ALT +left SHIFT +NUM LOCK
Switch MouseKeys on and off.
SHIFT five times
Switch StickyKeys on and off.
NUM LOCK for five seconds
Switch ToggleKeys on and off.
+U
Open Utility Manager


Press
To
END
Display the bottom of the active window.
HOME
Display the top of the active window.
NUM LOCK+ASTERISK on numeric keypad (*)
Display all subfolders under the selected folder.
NUM LOCK+PLUS SIGN on numeric keypad (+)
Display the contents of the selected folder.
NUM LOCK+MINUS SIGN on numeric keypad (-)
Collapse the selected folder.
LEFT ARROW
Collapse current selection if it's expanded, or select parent folder.
RIGHT ARROW
Display current selection if it's collapsed, or select first subfolder.