⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disk.cc

📁 美国加州大学操作系统课程实验平台Nachos
💻 CC
字号:
// disk.cc //	Routines to simulate a physical disk device; reading and writing//	to the disk is simulated as reading and writing to a UNIX file.//	See disk.h for details about the behavior of disks (and//	therefore about the behavior of this simulation).////	Disk operations are asynchronous, so we have to invoke an interrupt//	handler when the simulated operation completes.////  DO NOT CHANGE -- part of the machine emulation//// Copyright (c) 1992-1993 The Regents of the University of California.// All rights reserved.  See copyright.h for copyright notice and limitation // of liability and disclaimer of warranty provisions.#include "copyright.h"#include "disk.h"#include "debug.h"#include "sysdep.h"#include "main.h"// We put a magic number at the front of the UNIX file representing the// disk, to make it less likely we will accidentally treat a useful file // as a disk (which would probably trash the file's contents).const int MagicNumber = 0x456789ab;const int MagicSize = sizeof(int);const int DiskSize = (MagicSize + (NumSectors * SectorSize));//----------------------------------------------------------------------// Disk::Disk()// 	Initialize a simulated disk.  Open the UNIX file (creating it//	if it doesn't exist), and check the magic number to make sure it's // 	ok to treat it as Nachos disk storage.////	"toCall" -- object to call when disk read/write request completes//----------------------------------------------------------------------Disk::Disk(CallBackObj *toCall){    int magicNum;    int tmp = 0;    DEBUG(dbgDisk, "Initializing the disk.");    callWhenDone = toCall;    lastSector = 0;    bufferInit = 0;        sprintf(diskname,"DISK_%d",kernel->hostName);    fileno = OpenForReadWrite(diskname, FALSE);    if (fileno >= 0) {		 	// file exists, check magic number 	Read(fileno, (char *) &magicNum, MagicSize);	ASSERT(magicNum == MagicNumber);    } else {				// file doesn't exist, create it        fileno = OpenForWrite(diskname);	magicNum = MagicNumber;  	WriteFile(fileno, (char *) &magicNum, MagicSize); // write magic number	// need to write at end of file, so that reads will not return EOF        Lseek(fileno, DiskSize - sizeof(int), 0);		WriteFile(fileno, (char *)&tmp, sizeof(int));      }    active = FALSE;}//----------------------------------------------------------------------// Disk::~Disk()// 	Clean up disk simulation, by closing the UNIX file representing the//	disk.//----------------------------------------------------------------------Disk::~Disk(){    Close(fileno);}//----------------------------------------------------------------------// Disk::PrintSector()// 	Dump the data in a disk read/write request, for debugging.//----------------------------------------------------------------------static voidPrintSector (bool writing, int sector, char *data){    int *p = (int *) data;    if (writing)        cout << "Writing sector: " << sector << "\n";     else        cout << "Reading sector: " << sector << "\n";     for (unsigned int i = 0; i < (SectorSize/sizeof(int)); i++) {	cout << p[i] << " ";    }    cout << "\n"; }//----------------------------------------------------------------------// Disk::ReadRequest/WriteRequest// 	Simulate a request to read/write a single disk sector//	   Do the read/write immediately to the UNIX file//	   Set up an interrupt handler to be called later,//	      that will notify the caller when the simulator says//	      the operation has completed.////	Note that a disk only allows an entire sector to be read/written,//	not part of a sector.////	"sectorNumber" -- the disk sector to read/write//	"data" -- the bytes to be written, the buffer to hold the incoming bytes//----------------------------------------------------------------------voidDisk::ReadRequest(int sectorNumber, char* data){    int ticks = ComputeLatency(sectorNumber, FALSE);    ASSERT(!active);				// only one request at a time    ASSERT((sectorNumber >= 0) && (sectorNumber < NumSectors));        DEBUG(dbgDisk, "Reading from sector " << sectorNumber);    Lseek(fileno, SectorSize * sectorNumber + MagicSize, 0);    Read(fileno, data, SectorSize);    if (debug->IsEnabled('d'))	PrintSector(FALSE, sectorNumber, data);        active = TRUE;    UpdateLast(sectorNumber);    kernel->stats->numDiskReads++;    kernel->interrupt->Schedule(this, ticks, DiskInt);}voidDisk::WriteRequest(int sectorNumber, char* data){    int ticks = ComputeLatency(sectorNumber, TRUE);    ASSERT(!active);    ASSERT((sectorNumber >= 0) && (sectorNumber < NumSectors));        DEBUG(dbgDisk, "Writing to sector " << sectorNumber);    Lseek(fileno, SectorSize * sectorNumber + MagicSize, 0);    WriteFile(fileno, data, SectorSize);    if (debug->IsEnabled('d'))	PrintSector(TRUE, sectorNumber, data);        active = TRUE;    UpdateLast(sectorNumber);    kernel->stats->numDiskWrites++;    kernel->interrupt->Schedule(this, ticks, DiskInt);}//----------------------------------------------------------------------// Disk::CallBack()// 	Called by the machine simulation when the disk interrupt occurs.//----------------------------------------------------------------------voidDisk::CallBack (){     active = FALSE;    callWhenDone->CallBack();}//----------------------------------------------------------------------// Disk::TimeToSeek()//	Returns how long it will take to position the disk head over the correct//	track on the disk.  Since when we finish seeking, we are likely//	to be in the middle of a sector that is rotating past the head,//	we also return how long until the head is at the next sector boundary.//	//   	Disk seeks at one track per SeekTime ticks (cf. stats.h)//   	and rotates at one sector per RotationTime ticks//----------------------------------------------------------------------intDisk::TimeToSeek(int newSector, int *rotation) {    int newTrack = newSector / SectorsPerTrack;    int oldTrack = lastSector / SectorsPerTrack;    int seek = abs(newTrack - oldTrack) * SeekTime;				// how long will seek take?    int over = (kernel->stats->totalTicks + seek) % RotationTime; 				// will we be in the middle of a sector when				// we finish the seek?    *rotation = 0;    if (over > 0)	 	// if so, need to round up to next full sector   	*rotation = RotationTime - over;    return seek;}//----------------------------------------------------------------------// Disk::ModuloDiff()// 	Return number of sectors of rotational delay between target sector//	"to" and current sector position "from"//----------------------------------------------------------------------int Disk::ModuloDiff(int to, int from){    int toOffset = to % SectorsPerTrack;    int fromOffset = from % SectorsPerTrack;    return ((toOffset - fromOffset) + SectorsPerTrack) % SectorsPerTrack;}//----------------------------------------------------------------------// Disk::ComputeLatency()// 	Return how long will it take to read/write a disk sector, from//	the current position of the disk head.////   	Latency = seek time + rotational latency + transfer time//   	Disk seeks at one track per SeekTime ticks (cf. stats.h)//   	and rotates at one sector per RotationTime ticks////   	To find the rotational latency, we first must figure out where the //   	disk head will be after the seek (if any).  We then figure out//   	how long it will take to rotate completely past newSector after //	that point.////   	The disk also has a "track buffer"; the disk continuously reads//   	the contents of the current disk track into the buffer.  This allows //   	read requests to the current track to be satisfied more quickly.//   	The contents of the track buffer are discarded after every seek to //   	a new track.//----------------------------------------------------------------------intDisk::ComputeLatency(int newSector, bool writing){    int rotation;    int seek = TimeToSeek(newSector, &rotation);    int timeAfter = kernel->stats->totalTicks + seek + rotation;#ifndef NOTRACKBUF	// turn this on if you don't want the track buffer stuff    // check if track buffer applies    if ((writing == FALSE) && (seek == 0) 		&& (((timeAfter - bufferInit) / RotationTime) 	     		> ModuloDiff(newSector, bufferInit / RotationTime))) {        DEBUG(dbgDisk, "Request latency = " << RotationTime);	return RotationTime; // time to transfer sector from the track buffer    }#endif    rotation += ModuloDiff(newSector, timeAfter / RotationTime) * RotationTime;    DEBUG(dbgDisk, "Request latency = " << (seek + rotation + RotationTime));    return(seek + rotation + RotationTime);}//----------------------------------------------------------------------// Disk::UpdateLast//   	Keep track of the most recently requested sector.  So we can know//	what is in the track buffer.//----------------------------------------------------------------------voidDisk::UpdateLast(int newSector){    int rotate;    int seek = TimeToSeek(newSector, &rotate);        if (seek != 0)	bufferInit = kernel->stats->totalTicks + seek + rotate;    lastSector = newSector;    DEBUG(dbgDisk, "Updating last sector = " << lastSector << " , " << bufferInit);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -