[ RCOS.java Home | RCOS Home | David's Home ]
Name: |
Disk |
Comment: |
The following class defines a physical disk I/O device. The disk
has a single surface, split up into "tracks", and each track split
up into "sectors" (the same number of sectors on each track, and each
sector has the same number of bytes of storage).
Addressing is by sector number -- each sector on the disk is given a unique number: track * SectorsPerTrack + offset within a track. As with other I/O devices, the raw physical disk is an asynchronous device -- requests to read or write portions of the disk return immediately, and an interrupt is invoked later to signal that the operation completed. The physical disk is in fact simulated via operations on a UNIX file. To make life a little more realistic, the simulated time for each operation reflects a "track buffer" -- RAM to store the contents of the current track as the disk head passes by. The idea is that the disk always transfers to the track buffer, in case that data is requested later on. This has the benefit of eliminating the need for "skip-sector" scheduling -- a read request which comes in shortly after the head has passed the beginning of the sector can be satisfied more quickly, because its contents are in the track buffer. Most disks these days now come with a track buffer. The track buffer simulation can be disabled by compiling with -DNOTRACKBUF |
Collaborators: |
#define SectorSize 128 // number of bytes per disk sector #define SectorsPerTrack 32 // number of sectors per disk track #define NumTracks 32 // number of tracks per disk #define NumSectors (SectorsPerTrack * NumTracks) // total # of sectors per disk 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); };