This document provides instructions for the installation of the MOSS File System Simulator on Unix operating systems. This procedure should be the same or similar on Unix, Linux, Solaris, HP-UX and other Unix-compatible systems.
The MOSS software is designed for use with Andrew S. Tanenbaum, Modern Operating Systems, 2nd Edition (Prentice Hall, 2001). The File System Simulator and documentation were written by Ray Ontko (rayo@ontko.com).
The following software components are required to install and use the MOSS File System Simulator.
Java Development Kit (JDK) 1.0 or greater
Text program editor (e.g., notepad)
Installation of the software can be accomplished with these simple steps:
Create a directory in which you wish to install the simulator (e.g., "moss/filesys").
cd
mkdir moss
cd moss
mkdir filesys
cd filesys
Download the compressed tar archive (filesys.tgz) into the directory.
Expand the compressed tar archive.
$ tar -xzf filesys.tgz
or
$ gunzip filesys.tgz
$ tar xf filesys.tar
The directory should now contain the following files:
Files |
Description |
---|---|
filesys.tgz |
Compressed tar archive which contains all the other files. |
BitBlock.java |
Java source files (*.java) |
BitBlock.class |
Compiled Java class files (*.class) |
Documentation |
|
Directory containing documentation on java classes (generated by the javadoc utility). |
|
Gnu General Public License: Terms and Conditions for Copying, Distribution, and Modification |
The distribution includes compiled class files as well as the source java files. You should not need to recompile unless you decide to change the code. If you wish to compile the code, the following commands should work if you're using a Java compiler that accepts the normal "javac" command line.
To determine which shell you're using:
$ echo $SHELL
If you're using sh, ksh, bash:
$ CLASSPATH=.
$ export CLASSPATH
$ javac *.java
If you're using csh, tcsh:
% set CLASSPATH=.
% javac *.java
To test the program, enter the following sequence of commands.
$ java mkfs filesys.dat 256 16
$ java mkdir /root
$ java ls /
$ ls *.java | java tee /root/t.lis
$ java ls /root
$ java cat /root/t.lis
If things are working correctly, the program will produce output that looks something like this:
$ java mkfs filesys.dat 256 16
block_size: 256
blocks: 16
super_blocks: 1
free_list_blocks: 1
inode_blocks: 3
data_blocks: 11
block_total: 16
$ java mkdir /root
$ java ls /
/:
0 48 .
0 48 ..
1 32 root
total files: 3
$ ls *.java | java tee /root/t.lis
BitBlock.java
Block.java
DirectoryEntry.java
FileDescriptor.java
FileSystem.java
IndexNode.java
Kernel.java
ProcessContext.java
Stat.java
SuperBlock.java
cat.java
cp.java
dump.java
ls.java
mkdir.java
mkfs.java
tee.java
$ java ls /root
/root:
1 48 .
0 48 ..
2 219 t.lis
total files: 3
$ java cat /root/t.lis
BitBlock.java
Block.java
DirectoryEntry.java
FileDescriptor.java
FileSystem.java
IndexNode.java
Kernel.java
ProcessContext.java
Stat.java
SuperBlock.java
cat.java
cp.java
dump.java
ls.java
mkdir.java
mkfs.java
tee.java
This document is a user guide for the MOSS File System Simulator. It explains how to use the simulator and describes the programs and the various input files used by and output files produced by the simulator. The MOSS software is designed for use with Andrew S. Tanenbaum, Modern Operating Systems, 2nd Edition (Prentice Hall, 2001). The File System Simulator and documentation were written by Ray Ontko (rayo@ontko.com).
The file system simulator shows the inner workings of a UNIX V7 file system. The simulator reads or creates a file which represents the disk image, and keeps track of allocated and free blocks using a bit map. A typical exercise might be for students to write a program (in Java) which invokes various simulated operating system calls against a well-known disk image provided by the instructor. Students may also be asked to implement indirect blocks, list-based free block managment, or write a utility (like fsck) to check and repair the file system.
The MOSS File System Simulator is a collection of Java classes which simulate the file system calls available in a typical Unix-like operating system. The "Kernel" class contains methods (functions) like "creat()", "open()", "read()", "write()", "close()", etc., which read and write blocks in an underlying file in much the same way that a real file system would read and write blocks on an underlying disk device.
In addition to the "Kernel" class, there are a number of underlying classes to support the implementation of the kernel. The classes FileSystem, IndexNode, DirectoryEntry, SuperBlock, Block, BitBlock, FileDescriptor, and Stat contain all data structures and algorithms which implement the simulated file system.
Also included are a number of sample programs which can be used to operate on a simulated file system. The Java programs "ls", "cat", "mkdir", "mkfs", etc., perform file system operations to list directories, display files, create directories, and create (initialize) file systems. These programs illustrate the various file system calls and allow the user to carry out various read and write operations on the simulated file system.
As mentioned above, there is a backing file for our simulated file system. A "dump" program is included with the distribution so that you can examine this file, byte-by-byte. Any dump program may be used (e.g., the "od" program in Unix); we include this one which is simple to use and understand, and can be used with any operating system.
There are a number of ways you can use the simulator to get a better understanding of file systems. You can
use the provided utility programs (mkfs, mkdir, ls, cat, etc.) to perform operations on the simulated file system and use the dump program to examine the underlying file and observe any changes,
examine the sample utility programs to see how they use the system call interface to perform file operations,
enhance the sample utility programs to provide additional functionality,
write your own utility programs to extend the functionality of the simulated file system, and
modify the underlying Kernel and other implementation classes to extend the functionality of the
In the sections which follow, you will learn what you need to know to perform each of these activities.
The mkfs program creates a file system backing file. It does this by creating a file whose size is specified by the block size and number of blocks given. It writes the superblock, the free list blocks, the inode blocks, and the data blocks for a new file system. Note that it will overwrite any existing file of the name specified, so be careful when you use this program.
This program is similar to the "mkfs" program found in Unix-like operating systems.
The general format for the mkfs command is
java mkfs file-name block-size blocks
where
For example, the command
java mkfs filesys.dat 256 40
will create (or overwrite) a file "filesys.dat" so that it contains 40 256-byte blocks for a total of 10240 bytes.
The output from the command should look something like this:
block_size: 256
blocks: 40
super_blocks: 1
free_list_blocks: 1
inode_blocks: 8
data_blocks: 30
block_total: 40
From the output you can see that one block is needed for the superblock, one for free list management, eight for index nodes, and the remaining 30 are available for data blocks.
Why is there 1 block for free list management? Note that 30 blocks require 30 bits in the free list bitmap. Since 256 bytes/block * 8 bits/byte = 2048 bits/block, clearly one bitmap block is sufficient to track block allocation for this file system.
Why are there 8 blocks for index nodes? Note that 30 blocks could result in 30 inodes if many one-block files or directories are created. Since each inode requires 64 bytes, only 4 will fit in a block. Therefore, 8 blocks are set aside for up to 32 inodes.
The mkdir program can be used to create new directories in our simulated file system. It does this by creating the file specified as a directory file, and then writing the directory entries for "." and ".." to the newly created file. Note that all directories leading to the new directory must already exist.
This program is similar to the "mkdir" command in Unix-like and MS-DOS-related operating systems.
The general format for the mkdir command is
java mkdir directory-path
where
For example, the command
java mkdir /home
creates a directory called "home" as a subdirectory of the root directory of the file system.
Similarly, the command
java mkdir /home/rayo
creates a directory called "rayo" as a subdirectory of the "home" directory, which is presumed to already exist as a subdirectory of the root directory of the file system.
The ls program is used to list information about files and directories in our simulated file system. For each file or directory name given it displays information about the files named, or in the case of directories, for each file in the directories named.
This program is similar to the "ls" command in Unix-like operating systems, or the "dir" command in DOS-related operating systems.
The general format for the ls command is
java ls path-name ...
where
For example, the command
java ls /home
lists the contents of the "/home" directory. For each file in the directory, a line is printed showing the name of the file or subdirectory, and other pertinent information such as size.
The output from the command should look something like this:
/home:
1 48 .
0 48 ..
2 32 rayo
total files: 3
In this case we see that the "/home" directory contains entries for ".", "..", and "rayo".
The tee program reads from standard input and writes whatever is read to both standard output and the named file. You can use this program to create files in our simulated file system with content created in the operating system environment.
This program is similar to the "tee" command found in many Unix-like operating systems.
The general format for the tee command is
java tee file-path
where
For example,
echo "howdy, podner" | java tee /home/rayo/hello.txt
causes the single line "howdy, podner" to be written to the file "/home/rayo/hello.txt".
The output from the command is
howdy, podner
which you should note was the same as the input sent to the tee program by the "echo" command.
Note that the "|" (pipe) is almost always used with the tee program. Users of Unix-like operating systems will find the "echo", and "cat" commands useful to produce input for the pipe to tee. Users of MS-DOS-related operating systems will find the "echo" and "type" commands to be useful in this regard.
If you wish to simply enter text directly to a file, then you may use tee directly (i.e., without the pipe). Users of Unix-like operating systems will need to use CTRL-D to signal the end of input. Users of MS-DOS-related operating systems will need to use CTRL-Z to signal the end of input.
The cp program allows you to copy the contents from one file to another in our simulated file system. If the destination file already exists, it will be overwritten.
This program is similar to the "cp" command in Unix-like operating systems, and the "copy" command in MS-DOS-related operating systems.
The general format of the "cp" command is
java cp input-file-name output-file-name
where
For example,
java cp /home/rayo/hello.txt /home/rayo/greeting.txt
creates a new file "/home/rayo/greeting.txt" by copying to it the contents of file "/home/rayo/hello.txt".
The cat program reads the contents of a named file and writes it to standard output. The cat program is generally used to display the contents of a file.
This program is similar to the "cat" command in Unix-like operating systems, or the "type" command in MS-DOS-related operating systems.
The general format of the cat command line is
java cat file-name
where
For example,
java cat /home/rayo/greeting.txt
causes the file "/home/rayo/greeting.txt" to be read, the contents of which are written to standard output.
In this case, the output from the program might look something like this
howdy, podner
While you are working with the file system simulator, you may wish to dump the contents of the backing file to see if it contains what you think it contains. The dump program shows the contents of a file in the operating environment, one byte at a time, in various formats (hexadecimal, decimal, ASCII).
Note that dump dumps the contents of a real file, not a file in our simulated file system.
The general format of the dump command line is
java dump file-name
where
The general format of the dump output is
addr hex dec asc
where
Each line of dump output corresponds to a single byte in the file. To keep the listing brief, dump only displays non-zero bytes from the input file.
For example
java dump filesys.dat | more
causes the contents of the file "filesys.dat" to be displayed, one line per byte. The "| more" causes you to be prompted for each page of the output.
The first page of the output should look something like this:
0 1 1
5 28 40 (
9 1 1
13 2 2
17 a 10
256 1f 31
512 40 64 @
515 3 3
523 30 48 0
527 ff 255
528 ff 255
529 ff 255
530 ff 255
531 ff 255
532 ff 255
533 ff 255
534 ff 255
535 ff 255
536 ff 255
537 ff 255
538 ff 255
539 ff 255
540 ff 255
541 ff 255
You should notice, for example, that the first block (the super block) contains a few numeric values corresponding to the block size (the 1 in the 0 byte means 256), number of blocks, etc. The second block (starting at byte 256) contains a few bits that are set, indicating that the first few blocks are allocated. The third block (starting at 512) contains a few index nodes; the FF/255 values indicate that a direct block is unallocated. A little further down you will see ".", and ".." for the directory entries for the root file system, and other data blocks.
Each file system simulator program must call Kernel.initialize() before calling any of the other Kernel methods. The initialize() method reads a configuration file ("filesys.conf" is the default), opens the backing file for the file system ("filesys.dat" is the default), and performs other initializations. This section of the user guide describes the various options which may be set in the configuration file.
Name |
Description |
Default Value |
---|---|---|
filesystem.root.filename |
The name of the file containing the root file system for the simulation. |
filesys.dat |
filesystem.root.mode |
The mode to use when opening the root file system backing file. The mode should either be "rw" for reading and writing, or "r" for read-only access. |
rw |
process.uid |
The numeric user id (uid) to use for the default process context. This should be a number between 0 and 32767. |
1 |
process.gid |
The numeric group id (gid) to use for the default process context. This should be a number between 0 and 32767. |
1 |
process.umask |
The umask to use for the default process context. This should be an octal number between 000 and 777. |
022 |
process.dir |
The working directory in the simulated file system to be used for the default process context. This should be a string that starts with "/". |
/root |
process.max_open_files |
The maximum number of files that may be open at a time by a process. When a process context is created, this many slots are created for possible open files. |
10 |
kernel.max_open_files |
The maximum number of files that may be open at one time by all processes in the simulation. When the simulator starts, this many slots are created for possible open files. |
20 |
In addition to the standard configuration file, "filesys.conf", the distribution also includes a smaller sample configuration file, "sample.conf". This is shown below to illustrate a typical configuration file.
!
! my personal filesys configuration file
!
filesystem.root.filename = rayo.dat
filesystem.root.mode = r
process.uid = 1000
process.gid = 1000
process.umask = 002
process.dir = /home/rayo
In this particular example, the file system is contained in the backing file "rayo.dat", which is here being opened for read-only access. The working directory for the default process context is "/home/rayo", with the uid, gid, and umask shown.
The default configuration file is named "filesys.conf" and is included in the application distribution. You may modify this file directly to set various options, or you may create your own configuration file and specify the name of this new file when you launch your simulator programs.
If you choose to create your own configuration file, you will need to define a system property "filesys.conf" which contains the name of file. For example, suppose you wanted to run the "ls" program using "my_filesys.conf" as the configuration file. Your java command would look something like this:
java -Dfilesys.conf=my_filesys.conf ls /home
If there is no value set for the "filesys.conf" system property, then the name "filesys.conf" is used as the default configuration filename.
Writing programs that use the File System Simulator requires the use of the Kernel class, and may involve the use of the classes Stat and DirectoryEntry. If you're writing ordinary programs that use the standard file system calls, you should not need to reference any other classes.
These three classes are described briefly here. For more information, follow the link for the class to the javadoc for that class.
For more information about Unix system calls and the stat and dirent structs, refer to a Unix system manual. Users of Unix-like systems may find the commands "man -S 2 creat", "man -S 2 open", etc. to be helpful.
All programs that use the File System Simulator should adhere to the following guidelines:
Invoke the method Kernel.initialize() before any other File System Simulator calls.
Use Kernel.exit() when you wish to terminate processing in your program.
Check for errors after each system call (e.g., creat(), open(), read(), write(), etc.). Nearly all the system calls return -1 if an error occurs.
Use Kernel.perror() to print the message associated with an error.
Use Kernel.getErrno() to determine which error occurred, if needed. Note that in standard Unix programs you would reference the static process variable "errno".
For examples, take a look at the following sample programs in the distribution:
Collectively, these sample programs invoke all of the core methods (system calls) of the file system simulator.
Adding new features to the File System Simulator is an excellent way to probe your understanding of file system operation, and to investigate new features. Enhancements will almost certainly require changes to the class Kernel, and may necessitate changes to the sample programs described above. This section describes the other classes that implement the functionality of the simulator so that you may understand the intended organization of these components when making a proposed enhancement.
The following are the internal classes for the file system simulator:
Of course, you should look at the code and plan your enhancements carefully.
© Copyright 2001, Prentice-Hall, Inc. This program is free software; it is distributed under the terms of the Gnu General Public License. See copying.txt, included with this distribution.
Please send suggestions, corrections, and comments to Ray Ontko (rayo@ontko.com).
Last updated: September 29, 2001