| previous | contents | up | next |
This section will introduce you to the Unix filesystem and the concepts that surround it. Suffice it to say that a filesystem is exactly that, a system of files with some arrangement for organization and storage. Below, you will see how the typical way of doing this with a Unix operating system, although there are significant variations.
The currently popular method of storing data for Unix filesystems is on hard disk storage devices. This is actually so common, you may not even have considered there to be another way of storing filesystem data. In any case, this being the de facto method, we must understand a little about the physical disks the data reside on.
A hard disk is a device containing a circular "platter" (or several of them),
coated with magnetic material, which can be "written" to and "read" by
reorienting or sensing, respectively, the magnetic field trapped in the in the
disk coating. The platters spin about a central axis, and typically a platter
will contain a magnetic coating on each side, to be written to and read from
by the drive "heads". As the platters spin, the heads move radially allowing
the platters to spin under them. Thus all sections of the disk platter are
available to the drive head and may be chunked as sectors on a platter. Since
the drive must run at variable angular speeds to keep the disk travel under
the heads at a given radius at a constant rate (i.e. rate = angular
speed * radius), a virtual cylinder is described by the outline of head
travel, at a fixed radius, through 360 degrees of platter, vertically across
all platters. See the diagram below:
Therefore the data capacity of a disk is described best by:
A typical example for a 2.1 GB IDE disk on a Linux-based PC would be:Disk Capacity = Cylinders * Heads * Sectors * (# bytes / disk block)
C/H/S = 1024/64/63
Disk Capacity = 1024 * 64 * 63 * 512 bytes/block = 2113929216 bytes
= 2113929216 bytes / 1024 bytes/kB = 2064384 kilobytes
= 2064384 kB / 1024 kB/MB = 2016 megabytes
= 2016 MB / 1024 MB/GB = 1.97 gigabytes
But, wait! The salesman said this was a 2.1 GB disk! Something's wrong... Well, no, it's just in how you look at it. The question is what's in a kilobyte, a megabyte and a gigabyte. Take a look at this:
C/H/S = 1024/64/63
Disk Capacity = 1024 * 64 * 63 * 512 bytes/block = 2113929216 bytes
= 2113929216 bytes / 1000 bytes/kB = 2113929.22 kilobytes
= 2064384 kB / 1000 kB/MB = 2113.93 megabytes
= 2016 MB / 1000 MB/GB = 2.11 gigabytes
There it is! So, the answer is that you bought a 2113929216 byte disk.
The next level of abstraction from the actual hard disk geometry is at the level of disk "partitions". The disk capacity is described by a map, generally stored in the very first section of the disk, called the "disk label." The map specifies where each partition begins and what its extent is. It is this map, or "partition table", that provides the hooks on which to hang our filesystem starting points, commonly referred to as "mount points".
The disk label also contains two other necessary pieces of information for the operating system to boot: the disk geometry and the code to find the Unix kernel on the disk and load it. The drive geometry need not be the actual physical geometry, being instead a different geometry with the same capacity. In this case, the drive controller will actually translate to the physical geometry. This is simply a way to manufacture different disks that respond in the same way to the operating system and has no real value to the admin or the user. The kernel-loading code is generically referred to as the "boot loader", but has different names under different flavors of Unix (e.g. "lilo" for Linux and "sash" for IRIX).
The editing of a partition table goes beyond the scope of this course, but below are examples of disk label listings for both a Linux and an IRIX system:
IRIX disk label, generated with the "fx" command, with the
interactive argument "label/show/all":
|
Linux disk label, generated by "fdisk", with the interactive
argument "p":
Disk /dev/hda: 64 heads, 63 sectors, 1023 cylinders Units = cylinders of 4032 * 512 bytes Device Boot Start End Blocks Id System /dev/hda1 * 1 990 1995808+ 83 Linux /dev/hda2 991 1023 66528 5 Extended /dev/hda5 991 1023 66496+ 82 Linux swap |
The standard Unix filesystem, generically referred to as the "ufs" filesystem, is arranged on a disk partition using a "linked-list" of pointers to data. The structure of a partition begins with, or is defined by, the "superblock." The superblock is a data structure which includes information about the: type of filesystem (i.e. "ufs", "ext2fs", etc.), size and modification time of the the filesystem, list of free and allocated blocks and the first inode, which points to (you guessed it) the root directory, "/". The superblock is always replicated, to provide fault tolerance against disk failure in the first superblock.
Files are stored in the filesystem in two pieces: (1) a chunk of data somewhere in the filesystem; (2) a data structure which contains information about the location, size, creation/modification/access times, ownership, access attributes of and links to the file. This data structure is called an "inode." The only thing about the file not included in the inode is the name of the file. This is important, both to the concept of links and to disentangle it from directory management. Finally, directories bring the organization to a close, providing the linked list, referred to above. A directory is a binary file containing the name/inode pair mappings for files "contained" in the directory. Thus, the superblock provides the mapping to the root directory, and from there one can find any other file on the filesystem.
Reading and writing of data on disk file systems is usually buffered. Data are not actually read from disk for every read request made by a user, and they are not written to disk for every write request made by a user. Data pass through buffers on their way to and from disks. When a user program opens and reads from a file, more data are actually read from disk than were requested, and the extra data are stored in a buffer. Subsequent read requests are fulfilled from the buffer until the buffer is empty. Then, the buffer is filled by another read from the disk. When writing to files, data are written into a buffer until the buffer fills, and then, the contents of the buffer is written to disk.
How long will data sit in an output buffer if only a small amount of data are written to a file and the buffer is very slow to fill? Most Unix systems run a daemon that regularly flushes buffers. Flush times usually vary from 15 seconds to 1 minute. People who run Unix on laptops often set very long flush times to minimize disk writes and power consumption to prolong battery life.
Ordinary users can flush buffers by using the sync command. Buffers are also flushed when filesystems are unmounted using the umount command.
Buffered I/O has very important implications for disk users. File systems must be properly unmounted to ensure that all data are written to disk. If a floppy disk is popped out of the drive without having first been unmounted, data that remain in the buffer will be lost. Similarly, if someone turns off the power to a computer without having properly shutdown the computer, data that remain in output buffers are lost. The losses can be enormous.
| previous | contents | up | next |