In this roadmap we study the following issues associated with the file system:
As before, examine and understand the file system code first. Nachos file operations are similar (but not identical) to those in UNIX. It is a good idea to read the UNIX man pages for creat, open, close, read, write, lseek, and unlink (e.g., type "man creat").
Command line switches support the following file system operations:
-f causes the physical disk to be formatted -cp copies a file from UNIX to nachos -p prints a nachos file to stdout -r removes a nachos file from the file system -l lists the contents of the nachos directory -D prints the contents of the entire file system -t tests the performance of the nachos file system
Examples
./nachos -cp ../test/halt halt
Copy the halt program into the simulated disk.
./nachos -x halt
Run the halt program from the simulated disk.
./nachos -cp ../threads.cc threads.cc ./nachos -p threads.cc
Copy a textfile from UNIX into the nachos simulated disk and print it to stdout. See Example for a sample run of the file system.
Before tracing the program, we first give an overview of
nachos file system. It has the following objects:
FileSystem
{ OpenFile *freeMapFile; OpenFile *directoryFile; };
Directory
{ int tableSize; DirectoryEntry *table; };
DirectoryEntry
{ bool inUse; int sector; char name[FileNameMaxLen + 1]; };
OpenFile
{ FileHeader *hdr; int seekPosition; };
FileHeader
{ Int numBytes; int numSectors; int dataSectors[NumDirect]; };
---------- FileSystem ----------
| |
freeMapFile -------------------- directoryFile
| | |
BitMap OpenFile Directory
| |
FileHeader DirectoryEntry
Question
What file system objects exist in memory and/or on disk?
How are these objects moved between memory and disk?
Now, we examine nachos file system by tracing the program. Start with threads/system.cc/Initialize(argc, argv) called by threads/main.cc/main(int argc, char **argv).
void
Initialize(int argc, char **argv)
{
...
#ifdef FILESYS_NEEDED
if (!strcmp(*argv, "-f"))
format = TRUE;
#endif
...
#ifdef FILESYS
synchDisk = new SynchDisk("DISK");
#endif
#ifdef FILESYS_NEEDED
fileSystem = new FileSystem(format);
#endif
...
}
First, a new synchDisk is constructed before the fileSystem is created. The file system consists of a root directory and a bitmap, which we have studied in user program. Both the directory and bitmap are treated as files, objects of class OpenFile, which provides operations on files. Then, you can test this simple file system using command line switch. The utility functions can be found in fstest.cc.
class SynchDisk {
public:
SynchDisk(char* name); // Initialize a synchronous disk,
// by initializing the raw Disk.
~SynchDisk(); // De-allocate the synch disk data
void ReadSector(int sectorNumber, char* data);
// Read/write a disk sector, returning
// only once the data is actually read
// or written. These call
// Disk::ReadRequest/WriteRequest and
// then wait until the request is done.
void WriteSector(int sectorNumber, char* data);
void RequestDone(); // Called by the disk device interrupt
// handler, to signal that the
// current disk operation is complete.
private:
Disk *disk; // Raw disk device
Semaphore *semaphore; // To synchronize requesting thread
// with the interrupt handler
Lock *lock; // Only one read/write request
// can be sent to the disk at a time
};
SynchDisk::SynchDisk(char* name)
{
semaphore = new Semaphore("synch disk", 0);
lock = new Lock("synch disk lock");
disk = new Disk(name, DiskRequestDone, (int) this);
}
Questions:
class Disk {
public:
Disk(char* name, VoidFunctionPtr callWhenDone, int callArg);
// Create a simulated disk.
// Invoke (*callWhenDone)(callArg)
// every time a request completes.
~Disk(); // Deallocate the disk.
void ReadRequest(int sectorNumber, char* data);
// Read/write an single disk sector.
// These routines send a request to
// the disk and return immediately.
// Only one request allowed at a time!
void WriteRequest(int sectorNumber, char* data);
void HandleInterrupt(); // Interrupt handler, invoked when
// disk request finishes.
int ComputeLatency(int newSector, bool writing);
// Return how long a request to
// newSector will take:
// (seek + rotational delay + transfer)
private:
int fileno; // UNIX file number for simulated disk
VoidFunctionPtr handler; // Interrupt handler, to be invoked
// when any disk request finishes
int handlerArg; // Argument to interrupt handler
bool active; // Is a disk operation in progress?
int lastSector; // The previous disk request
int bufferInit; // When the track buffer started
// being loaded
int TimeToSeek(int newSector, int *rotate); // time to get to the new track
int ModuloDiff(int to, int from); // # sectors between to and from
void UpdateLast(int newSector);
};
Questions:
class FileSystem {
public:
...
private:
OpenFile* freeMapFile; // Bit map of free disk blocks,
// represented as a file
OpenFile* directoryFile; // "Root" directory -- list of
// file names, represented as a file
};
The file system consists of freeMapFile (OpenFile *), a bit map treated as a file, and directoryFile (OpenFile *), the root directory also treated as a file. Where are their file headers? The baseline file system has the following restrictions: only one (root) directory, entries in directory are of fixed size, maximum number of entries in the directory is 10.
FileSystem::FileSystem(bool format)
{
DEBUG('f', "Initializing the file system.\n");
if (format) {
BitMap *freeMap = new BitMap(NumSectors);
Directory *directory = new Directory(NumDirEntries);
FileHeader *mapHdr = new FileHeader;
FileHeader *dirHdr = new FileHeader;
DEBUG('f', "Formatting the file system.\n");
// First, allocate space for FileHeaders for the directory and bitmap
// (make sure no one else grabs these!)
freeMap->Mark(FreeMapSector);
freeMap->Mark(DirectorySector);
// Second, allocate space for the data blocks containing the contents
// of the directory and bitmap files. There better be enough space!
ASSERT(mapHdr->Allocate(freeMap, FreeMapFileSize));
ASSERT(dirHdr->Allocate(freeMap, DirectoryFileSize));
// Flush the bitmap and directory FileHeaders back to disk
// We need to do this before we can "Open" the file, since open
// reads the file header off of disk (and currently the disk has garbage
// on it!).
DEBUG('f', "Writing headers back to disk.\n");
mapHdr->WriteBack(FreeMapSector);
dirHdr->WriteBack(DirectorySector);
// OK to open the bitmap and directory files now
// The file system operations assume these two files are left open
// while Nachos is running.
freeMapFile = new OpenFile(FreeMapSector);
directoryFile = new OpenFile(DirectorySector);
// Once we have the files "open", we can write the initial version
// of each file back to disk. The directory at this point is completely
// empty; but the bitmap has been changed to reflect the fact that
// sectors on the disk have been allocated for the file headers and
// to hold the file data for the directory and bitmap.
DEBUG('f', "Writing bitmap and directory back to disk.\n");
freeMap->WriteBack(freeMapFile); // flush changes to disk
directory->WriteBack(directoryFile);
if (DebugIsEnabled('f')) {
freeMap->Print();
directory->Print();
delete freeMap;
delete directory;
delete mapHdr;
delete dirHdr;
}
} else {
// if we are not formatting the disk, just open the files representing
// the bitmap and directory; these are left open while Nachos is running
freeMapFile = new OpenFile(FreeMapSector);
directoryFile = new OpenFile(DirectorySector);
}
}
When the file system is constructed, if the command line switch is "-f", the disk is formatted (wipe out all files on the disk). It first initializes bitmap and root directory in memory (headers and files); flush the headers back to disk; open bitmap and root so that their headers are kept in memory and we can operate on them; flush bitmap and root directory files back to the disk; clean up memory. If the disk has been formatted, just open bitmap and root directory (bring their file headers into memory).
Question:
How many disk reads/writes when the file system is contructed with format=TRUE?
The file system provides the following operations. These operations are associated with the file system (directory, bitmap). The operations associated with individual files are in OpenFile object.
class FileSystem {
public:
...
bool Create(char *name, int initialSize);
OpenFile* Open(char *name);
bool Remove(char *name);
...
};
bool
FileSystem::Create(char *name, int initialSize)
{
Directory *directory;
BitMap *freeMap;
FileHeader *hdr;
int sector;
bool success;
DEBUG('f', "Creating file %s, size %d\n", name, initialSize);
directory = new Directory(NumDirEntries);
directory->FetchFrom(directoryFile);
if (directory->Find(name) != -1)
success = FALSE; // file is already in directory
else {
freeMap = new BitMap(NumSectors);
freeMap->FetchFrom(freeMapFile);
sector = freeMap->Find(); // find a sector to hold the file header
if (sector == -1)
success = FALSE; // no free block for file header
else if (!directory->Add(name, sector))
success = FALSE; // no space in directory
else {
hdr = new FileHeader;
if (!hdr->Allocate(freeMap, initialSize))
success = FALSE; // no space on disk for data
else {
success = TRUE;
// everthing worked, flush all changes back to disk
hdr->WriteBack(sector);
directory->WriteBack(directoryFile);
freeMap->WriteBack(freeMapFile);
}
delete hdr;
}
delete freeMap;
}
delete directory;
return success;
}
This function creates a file with no data by adding an entry in the directory. Study carefully the data movement between memory and disk.
The file header is flushed back to the disk before the directory. Because, if system crashes in between, the directory does not have the entry for the file although the file header is on the disk. The file system still functions. If, however, the order is reversed, the directory were flushed back before the file header. If the system crashes in between, we would have the entry in the directory referencing to a sector number (i-number) which is not the file header. The file system would be corrupted.
Question:
What if the system crashes after the directory is flushed back but before the free map is flushed back?
OpenFile *
FileSystem::Open(char *name)
{
Directory *directory = new Directory(NumDirEntries);
OpenFile *openFile = NULL;
int sector;
DEBUG('f', "Opening file %s\n", name);
directory->FetchFrom(directoryFile);
sector = directory->Find(name);
if (sector >= 0)
openFile = new OpenFile(sector); // name was found in directory
delete directory;
return openFile; // return NULL if not found
}
Steps of opening a file:
bool
FileSystem::Remove(char *name)
{
Directory *directory;
BitMap *freeMap;
FileHeader *fileHdr;
int sector;
directory = new Directory(NumDirEntries);
directory->FetchFrom(directoryFile);
sector = directory->Find(name);
if (sector == -1) {
delete directory;
return FALSE; // file not found
}
fileHdr = new FileHeader;
fileHdr->FetchFrom(sector);
freeMap = new BitMap(NumSectors);
freeMap->FetchFrom(freeMapFile);
fileHdr->Deallocate(freeMap); // remove data blocks
freeMap->Clear(sector); // remove header block
directory->Remove(name);
freeMap->WriteBack(freeMapFile); // flush to disk
directory->WriteBack(directoryFile); // flush to disk
delete fileHdr;
delete directory;
delete freeMap;
return TRUE;
}
This function removes a file from disk. In order to find the data sectors and free them, we must bring in the file header, which requires the directory file and the bitmap file.
Question:
What if the system crashes after the free map is flushed back but before the directory is flushed back?
class OpenFile {
public:
...
private:
FileHeader *hdr; // Header for this file
int seekPosition; // Current position within the file
};
Data structures: a pointer to FileHeader and a position.
------------------ | hdr |---> FileHeader ------------------ | seekPosition | |----------------|
OpenFile::OpenFile(int sector)
{
hdr = new FileHeader;
hdr->FetchFrom(sector);
seekPosition = 0;
}
int
OpenFile::Read(char *into, int numBytes)
{
int result = ReadAt(into, numBytes, seekPosition);
seekPosition += result;
return result;
}
int
OpenFile::Write(char *into, int numBytes)
{
int result = WriteAt(into, numBytes, seekPosition);
seekPosition += result;
return result;
}
int
OpenFile::ReadAt(char *into, int numBytes, int position)
{
int fileLength = hdr->FileLength();
int i, firstSector, lastSector, numSectors;
char *buf;
if ((numBytes <= 0) || (position >= fileLength))
return 0; // check request
if ((position + numBytes) > fileLength)
numBytes = fileLength - position;
DEBUG('f', "Reading %d bytes at %d, from file of length %d.\n",
numBytes, position, fileLength);
firstSector = divRoundDown(position, SectorSize);
lastSector = divRoundDown(position + numBytes - 1, SectorSize);
numSectors = 1 + lastSector - firstSector;
// read in all the full and partial sectors that we need
buf = new char[numSectors * SectorSize];
for (i = firstSector; i <= lastSector; i++)
synchDisk->ReadSector(hdr->ByteToSector(i * SectorSize),
&buf[(i - firstSector) * SectorSize]);
// copy the part we want
bcopy(&buf[position - (firstSector * SectorSize)], into, numBytes);
delete buf;
return numBytes;
}
int
OpenFile::WriteAt(char *from, int numBytes, int position)
{
int fileLength = hdr->FileLength();
int i, firstSector, lastSector, numSectors;
bool firstAligned, lastAligned;
char *buf;
if ((numBytes <= 0) || (position >= fileLength))
return 0; // check request
if ((position + numBytes) > fileLength)
numBytes = fileLength - position;
DEBUG('f', "Writing %d bytes at %d, from file of length %d.\n",
numBytes, position, fileLength);
firstSector = divRoundDown(position, SectorSize);
lastSector = divRoundDown(position + numBytes - 1, SectorSize);
numSectors = 1 + lastSector - firstSector;
buf = new char[numSectors * SectorSize];
firstAligned = (position == (firstSector * SectorSize));
lastAligned = ((position + numBytes) == ((lastSector + 1) * SectorSize));
// read in first and last sector, if they are to be partially modified
if (!firstAligned)
ReadAt(buf, SectorSize, firstSector * SectorSize);
if (!lastAligned && ((firstSector != lastSector) || firstAligned))
ReadAt(&buf[(lastSector - firstSector) * SectorSize],
SectorSize, lastSector * SectorSize);
// copy in the bytes we want to change
bcopy(from, &buf[position - (firstSector * SectorSize)], numBytes);
// write modified sectors back
for (i = firstSector; i <= lastSector; i++)
synchDisk->WriteSector(hdr->ByteToSector(i * SectorSize),
&buf[(i - firstSector) * SectorSize]);
delete buf;
return numBytes;
}
What happens when a new object OpenFile is constructed?
OpenFile provides operations, Read and Write, on files, which are implemented by ReadAt and WriteAt using the internal seekPosition. Note that we can only transfer one sector at a time from the disk, thus when read, we have to fetch all associated sectors from the disk into memory (kernel space) then copy what we want (read may not start from the beginning of the first sector and may not end at the end of the last sector). When write, we first fetch the first and the last sectors from the disk into the kernel space and then modify them and write all sectors back to the disk (the first and the last sectors may be partially modified).
class FileHeader {
public:
...
private:
int numBytes; // Number of bytes in the file
int numSectors; // Number of data sectors in the file
int dataSectors[NumDirect]; // Disk sector numbers for each data
// block in the file
};
Data structures of FileHeader:
------------------- | numBytes | ------------------- | numSectors | ------------------- | dataSectors[0] | ------------------- | dataSectors[1] | ------------------- | | | ... | | | -------------------
What is the value of NumDirect?
bool
FileHeader::Allocate(BitMap *freeMap, int fileSize)
{
numBytes = fileSize;
numSectors = divRoundUp(fileSize, SectorSize);
if (freeMap->NumClear() < numSectors)
return FALSE; // not enough space
for (int i = 0; i < numSectors; i++)
dataSectors[i] = freeMap->Find();
return TRUE;
}
void
FileHeader::Deallocate(BitMap *freeMap)
{
for (int i = 0; i < numSectors; i++) {
ASSERT(freeMap->Test((int) dataSectors[i])); // ought to be marked!
freeMap->Clear((int) dataSectors[i]);
}
}
void
FileHeader::FetchFrom(int sector)
{
synchDisk->ReadSector(sector, (char *)this);
}
There are two ways of initializing a file header:
How is the consistency checked when a file header is deallocated?
Compare the functions FetchFrom() and WriteBack() here with those in directory. The bitmap also has FetchFrom() and WriteBack() functions.
class DirectoryEntry {
public:
bool inUse; // Is this directory entry in use?
int sector; // Location on disk to find the
// FileHeader for this file
char name[FileNameMaxLen + 1]; // Text name for file, with +1 for
// the trailing '\0'
};
A directory is a table (array) of DirectoryEntry. The data structures of a DirectoryEntry:
------------
| inUse |
------------
| sector | sector number of file header
------------
| |
| name |
| |
------------
class Directory {
public:
...
void FetchFrom(OpenFile *file);
void WriteBack(OpenFile *file);
...
};
Compare FetchFrom() and WriteBack() functions with those in FileHeader.
void Copy(char *from, char *to) void Print(char *name) static void FileWrite() static void FileRead() void PerformanceTest()
This file provides some utility functions used for testing. It is a good idea to study UNIX file system calls.
Here is a sample run of the file system. Can you identify the disk reads/writes?
Script started on Mon Mar 06 10:22:46 199
church[1] cd filesys
church[2] gmake
...
church[3] ls
Makefile filehdr.cc list.o scheduler.o sysdep.o
addrspace.o filehdr.h machine.o stats.o system.o
bitmap.o filehdr.o main.o switch.o test
console.o filesys.cc mipssim.o swtch.s thread.o
directory.cc filesys.h nachos synch.o threadtest.o
directory.h filesys.o openfile.cc synchdisk.cc timer.o
directory.o fstest.cc openfile.h synchdisk.h translate.o
disk.o fstest.o openfile.o synchdisk.o typescript
exception.o interrupt.o progtest.o synchlist.o utility.o
church[4] nachos -f
No threads ready or runnable, and no pending interrupts.
Assuming the program completed.
Machine halting!
Ticks: total 82630, idle 82420, system 210, user 0
Disk I/O: reads 3, writes 5
Console I/O: reads 0, writes 0
Paging: faults 0
Network I/O: packets received 0, sent 0
Cleaning up...
church[20] nachos -cp ../test/halt halt
No threads ready or runnable, and no pending interrupts.
Assuming the program completed.
Machine halting!
Ticks: total 821010, idle 819810, system 1200, user 0
Disk I/O: reads 56, writes 51
Console I/O: reads 0, writes 0
Paging: faults 0
Network I/O: packets received 0, sent 0
Cleaning up...
church[21] nahos -x halt
Machine halting!
Ticks: total 5592, idle 5350, system 230, user 12
Disk I/O: reads 10, writes 0
Console I/O: reads 0, writes 0
Paging: faults 0
Network I/O: packets received 0, sent 0
Cleaning up...
church[22] nachos -cp filehdr.h filehdr.h
No threads ready or runnable, and no pending interrupts.
Assuming the program completed.
Machine halting!
Ticks: total 1150, idle 1000, system 150, user 0
Disk I/O: reads 2, writes 235
Console I/O: reads 0, writes 0
Paging: faults 0
Network I/O: packets received 0, sent 0
Cleaning up...
church[29] nachos -p filehdr.h
// filehdr.h
// Data structures for managing a disk file header.
//
....
int dataSectors[NumDirect]; // Disk sector numbers for each data
// block in the file
};
#endif // FILEHDR_H
No threads ready or runnable, and no pending interrupts.
Assuming the program completed.
Machine halting!
Ticks: total 131990, idle 129330, system 2660, user 0
Disk I/O: reads 253, writes 0
Console I/O: reads 0, writes 0
Paging: faults 0
Network I/O: packets received 0, sent 0
Cleaning up...
church[30] nachos -l
halt
filehdr.h
Ticks: total 2520, idle 2350, system 170, user 0
Disk I/O: reads 4, writes 0
Console I/O: reads 0, writes 0
church[32] nachos -D
Bit map file header:
FileHeader contents. File size: 128. File blocks:
2
File contents:
?\ff\ff\ff\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
\0\0\0\0\0\0\0\
0\0
Directory file header:
FileHeader contents. File size: 200. File blocks:
3 4
File contents:
\1\0\0\0\0\0\0\5halt\0\0\0\0\0\0\0\0\1\0\0\0\0\0\0\afilehdr.h\0\0\0\0\0\0\0\0\0\
0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
0\0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
Bitmap set:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22
, 23, 24, 25, 26, 27, 28, 29,
Directory contents:
Name: halt, Sector: 5
FileHeader contents. File size: 440. File blocks:
6 7 8 9
File contents:
\ad\df\ba\0\0\0\0\0(\0\0\0\90\1\0\0\90\1\0\0\b8\1\0\0\0\0\0\0\90\1\0\0\1c\f8\ff\
bf\0\0\0\0X\0\0\c\0\0\0\0\8\0\0\c! \0\0\0\0\2$\c\0\0\0\8\0\e0\3\0\0\0\0\1\0\2$\c
\0\0\0\8\0\e0\3\0\0\0\0\2\0\2$\c\0\0\0\8\0\e0\3\0\0\0\0\3\0\2$\c\0\0\0\8\0\e0\3\
0\0\0\0\4\0\2$\
c\0\0\0
\8\0\e0\3\0\0\0\0\5\0\2$\c\0\0\0\8\0\e0\3\0\0\0\0\6\0\2$\c\0\0\0\8\0\e0\3\0\0\0\
0\7\0\2$\c\0\0\0\8\0\e0\3\0\0\0\0\8\0\2$\c\0\0\0\8\0\e0\3\0\0\0\0\9\0\2$\c\0\0\0
\8\0\e0\3\0\0\0\0\a\0\2$\c\0\0\0\8\0\e0\3\0\0\0\0\b\0\2$\c\0\0\0\8\0\e0\3\0\0\0\
0\c\0\2$\c\0\0\
0
\8\0\e0\3\0\0\0\0\d\0\2$\c\0\0\0\8\0\e0\3\0\0\0\0\e\0\2$\c\0\0\0\8\0\e0\3\0\0\0\
0\f\0\2$\c\0\0\0\8\0\e0\3\0\0\0\0\10\0\2$\c\0\0\0\8\0\e0\3\0\0\0\0\11\0\2$\c\0\0
\0\8\0\e0\3\0\0\0\0\12\0\2$\c\0\0\0\8\0\e0\3\0\0\0\0\13\0\2$\c\0\0\0\8\0\e0\3\0\
0\0\0\8\0\e0\3\
0\0\0\0
\0\0\0\0\0\0\0\0\e8\ff\bd'\14\0\bf\af\10\0\be\afT\0\0\c!\f0\a0\3\4\0\0\c\0\0\0\0
!\e8\c0\3\14\0\bf\8f\10\0\be\8f\8\0\e0\3\18\0\bd'
Name: filehdr.h, Sector: 10
FileHeader contents. File size: 2327. File blocks:
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
File contents:
// filehdr.h \a//\9Data structures for managing a disk file header. \a//\a//\9A
file header describes where on disk to find the data
in a file,\a//\9along with other information about the file (for instance, its\
a//\9length, owner, etc.)\a//\a// Copyright (c) 1992-1
993 The Regents of the University of California.\a// All rights reserved. See c
opyright.h for copyright notice and limitation \a/
/ of liability and disclaimer of warranty provisions.\a\a#include "copyright.h"\
a\a#ifndef FILEHDR_H\a#define FILEHDR_H\a\a#include "di
sk.h"\a#include "bitmap.h"\a\a#define NumDirect \9((SectorSize - 2 * sizeof(int)
) / sizeof(int))\a#define MaxFileSize \9(NumDirect * S
ectorSize)\a\a// The following class defines the Nachos "file header" (in UNIX t
erms, \a// the "i-node"), describing where on disk
to find all of the data in the file.\a// The file header is organized as a simp
le table of pointers to\a// data blocks. \a//\a// Th
e file header data structure can be stored in memory or on disk.\a// When it is
on disk, it is stored in a single sector -- this
means\a// that we assume the size of this data structure to be the same\a// as o
ne disk sector. Without indirect addressing, this
\a// limits the maximum file length to just under 4K bytes.\a//\a// There is no
constructor; rather the file header can be initiali
zed\a// by allocating blocks for the file (if it is a new file), or by\a// readi
ng it from disk.\a\aclass FileHeader {\a public:\a
bool Allocate(BitMap *bitMap, int fileSize);// Initialize a file header, \a\9\9
\9\9\9\9// including allocating space \a\9\9\9\9\9\9// on di
sk for the file data\a void Deallocate(BitMap *bitMap); \9\9// De-allocate t
his file's \a\9\9\9\9\9\9// data blocks\a\a void FetchFr
om(int sectorNumber); \9// Initialize file header from disk\a void WriteBack(
int sectorNumber); \9// Write modifications to file
header\a\9\9\9\9\9// back to disk\a\a int ByteToSector(int offset);\9// Con
vert a byte offset into the file\a\9\9\9\9\9// to the disk sect
or containing\a\9\9\9\9\9// the byte\a\a int FileLength();\9\9\9// Return the
length of the file \a\9\9\9\9\9// in bytes\a\a void Print();\9\9\9
// Print the contents of the file.\a\a private:\a int numBytes;\9\9\9// Numb
er of bytes in the file\a int numSectors;\9\9\9// Numbe
r of data sectors in the file\a int dataSectors[NumDirect];\9\9// Disk sector
numbers for each data \a\9\9\9\9\9// block in the file\a}
;\a\a#endif // FILEHDR_H\a
Ticks: total 17970, idle 17490, system 480, user 0
Disk I/O: reads 35, writes 0
Console I/O: reads 0, writes 0
Paging: faults 0
Network I/O: packets received 0, sent 0
Cleaning up...
church[33] exit
script done on Mon Mar 02 10:33:24 199