Diseño del curso del sistema operativo de la Escuela de Software de la Universidad de Shandong Nachos-Experiment 4-Extensión del sistema de archivos básico

Nota: estos experimentos escritos en el blog no son completos y no son la versión final del informe experimental enviado (es una simple nota registrada por Typora durante el experimento), el contenido completo (incluido el código + el informe experimental) se puede pasar ( Diseño del curso del sistema operativo de la Universidad de software de la Universidad de Shandong ) descárguelo o siga el "blog de Moxi" para obtenerlo gratis
inserte la descripción de la imagen aquí

1. Análisis del sistema de archivos

Mirando el constructor del sistema de archivos en /filesys/filesys.cc, puede encontrar la siguiente información

#define FreeMapSector 		0
#define DirectorySector 	1
#define FreeMapFileSize 	(NumSectors / BitsInByte)
#define NumDirEntries 		10
#define DirectoryFileSize 	(sizeof(DirectoryEntry) * NumDirEntries)

FileSystem::FileSystem(bool format)
{
    
     
    if (format) {
    
       // 是否应该初始化磁盘
      BitMap *freeMap = new BitMap(NumSectors); // 创建文件位图
      Directory *directory = new Directory(NumDirEntries); // 创建包含10个文件目录项的文件目录表
      FileHeader *mapHdr = new FileHeader; // 创建文件位图的文件头
      FileHeader *dirHdr = new FileHeader; // 创建文件目录表的文件头
      
      // 第一步:文件位图中标记0、1号扇区被占用
      freeMap->Mark(FreeMapSector);		// 0号扇区为文件位图文件头
      freeMap->Mark(DirectorySector); // 1号扇区为文件目录表文件头

			// 第二步:在文件系统中分配位图文件与文件目录表的空间(传入文件位图与空间大小)
      ASSERT(mapHdr->Allocate(freeMap, FreeMapFileSize));   // 位图文件大小为128字节,1个扇区
      ASSERT(dirHdr->Allocate(freeMap, DirectoryFileSize)); // 十个文件目录项大小

			// 第三步:将更新后的位图文件头、文件目录表文件头写入磁盘
      mapHdr->WriteBack(FreeMapSector);   // 传入对应文件头所在扇区号
      dirHdr->WriteBack(DirectorySector);

      // 第四步:创建位图文件、文件目录表的Openfile, Openfile中存储文件头与文件读写位置
      freeMapFile = new OpenFile(FreeMapSector);			// 传入文件头所在扇区, 用于创建Openfile文件头
      directoryFile = new OpenFile(DirectorySector);	// 文件读写位置初始为0
     
			// 第五步:将位图文件信息、文件目录项信息传入对应Openfile中
      freeMap->WriteBack(freeMapFile);	 // 确定Openfile的起始扇区与结束扇区,开辟文件缓冲区
      directory->WriteBack(directoryFile); // 初始化整个文件
    } else {
    
    
      // 非初始化操作,则根据原有位图文件头、文件目录表文件头信息初始化Openfile
      freeMapFile = new OpenFile(FreeMapSector);
      directoryFile = new OpenFile(DirectorySector);
    }
}

Incluye principalmente el archivo de mapa de bits, el encabezado del archivo de la tabla del directorio de archivos, la creación de Openfile y la información de inicialización se escribe en el disco. Entre ellos, el archivo de mapa de bits utiliza 0 y 1 de cada bit para indicar si la posición del disco está libre. Al asignar, se buscará desde antes, y una vez que haya una posición libre, se asignará directamente. Además, en la sección anterior sobre la creación del sistema de archivos, se puede encontrar que el tamaño del archivo no se puede cambiar después de crearlo .

Los siguientes dos comandos de archivo que debemos implementar nosotros mismos, -ap, -hap

nachos [-df] -ap UNIX_filename nachos_filename: Indica que el contenido de un archivo UNIX se agregará al final del archivo nachos.
nachos [-df] -hap UNIX_filename nachos_filename: Indica que el contenido de un archivo UNIX comienza desde la parte media del archivo nachos y se agrega hacia atrás y cubre la segunda mitad del archivo nachos.

2. Extensión del sistema de archivos

1. Versión antigua

Implementación de los comandos nachos -ap y -hap

Primero observe cómo se implementa el comando nachos -ap en main.cc

else if (!strcmp(*argv, "-ap")) {
    
      // append from UNIX to Nachos
    ASSERT(argc > 2);
    Append(*(argv + 1), *(argv + 2), 0);
    argCount = 3;
}

Se puede encontrar que el comando "-ap" llama a la función Append(), que principalmente llama a OpenFile::Write()

OpenFile::Write(char *into, int numBytes)
{
    
    
   int result = WriteAt(into, numBytes, seekPosition);
   seekPosition += result;
   return result;
}

OpenFile::Write() llama a OpenFile::WriteAt(), por lo que a continuación consideraremos cómo modificar la función OpenFile::WriteAt() para implementar esta función.

El análisis de la función WriteAt original muestra que la función original no admite la escritura de datos que excedan el tamaño original de su archivo, por lo que debemos modificar la función ahora.

// 检查输入是否合法以及避免输入数据超过文件大小
if ((numBytes <= 0) || (position >= fileLength))  // For original Nachos file system
    //if ((numBytes <= 0) || (position > fileLength))  // For lab4 ...
    return 0;				
// check request
if ((position + numBytes) > fileLength)
    numBytes = fileLength - position;

Luego implemente estos dos comandos

La idea general es modificar el método WriteAt, si los datos escritos exceden el tamaño del archivo, expandirlo y solicitar nuevo espacio de memoria. A continuación, llame a la función WriteBack de OpenFile para volver a escribir en el disco. Esta función implementa la operación de reescritura de datos llamando al método WriteBack de filehdr. Cuando necesitamos volver a escribir el encabezado del archivo modificado en el disco duro, necesitamos obtener el número de sector donde se encuentra el encabezado del archivo Se agrega una variable de sector a la clase OpenFile para registrar el número de sector donde se encuentra el encabezado del archivo.

Primero, implemente la función ExtendSpace, el método de modificar el tamaño del archivo, complete la extensión del archivo y asígnele suficientes sectores de acuerdo con el tamaño del archivo.

Primero agregue el método bool ExtendSpace(int newSize); a la definición de clase en el archivo fileheader.h; luego implemente el método FileHeader::ExtendSpace en el archivo fileheader.cc

Idea de implementación: primero, determine si el sector de datos debe expandirse de acuerdo con el tamaño de los datos. Aquí hay dos casos. Si no, simplemente modifique el tamaño del archivo. Si es necesario, asigne el sector y luego modifique el tamaño.

bool
FileHeader::Extend(int newSize)
{
    
    
    if(newSize<numBytes)return FALSE;   //if not a extend operation
    if(newSize==numBytes)return TRUE;   //if size not change
	//计算所需的空间
    int newNumSectors  = divRoundUp(newSize, SectorSize);   //the number of sectors the new size need to be allocated.
    //如果所需空间等于numSectors(原有的空间)
    if(newNumSectors == numSectors){
    
    
        //设置一下大小
        numBytes = newSize; 
        return TRUE; 
    }
	//否则计算一下还需要申请的空间
    int diffSector = newNumSectors - numSectors;    
	
    OpenFile *bitmapfile = new OpenFile(0);
    BitMap *freeMap;//新建一个位图
    freeMap = new BitMap(NumSectors);
    freeMap->FetchFrom(bitmapfile);//从磁盘中取出位图
	printf("debug in fhdr extend where new Sector=%d \n",freeMap->NumClear());
    //if disk is full or file size is too big.
    if(newNumSectors>NumDirect||freeMap->NumClear()< diffSector)return FALSE;   
	//申请新的空间,并且存储到文件头
    int i;
    //i从numSectors到newNumSectors,即循环diffSector次
    for(i = numSectors; i<newNumSectors; i++)
    {
    
    
        dataSectors[i] = freeMap->Find();
    }
    numBytes = newSize;
    numSectors = newNumSectors;

    return TRUE;
}

A continuación, implemente el método WriteBack():

Agregue la declaración del método void WriteBack(); en la definición de clase del archivo openfile.h, y luego agregue el atributo int sector; para registrar el número de sector donde se encuentra el encabezado del archivo

class OpenFile {
    
    
  public:
 
//2021.11.21add+++++++++++++++++++++++++++++++++++
	void WriteBack();
//2021.11.21add+++++++++++++++++++++++++++++++++++
private:
  
//2021.11.21add++++++++++++++++++++++++++++++++
	int sector;
//2021.11.21add++++++++++++++++++++++++++++++++

Agregue this->ector = sector; en el archivo openfile.cc constructor.

OpenFile::OpenFile(int sector)
{
    
     
//2021.11.21add++++++++++++++++++++++++++++++++++++++++
	this->sector = sector;
//2021.11.21add++++++++++++++++++++++++++++++++++++++++

Modificar el manejo de (posición + numBytes) > fileLength en el método WriteAt

//2021.11.21add++++++++++++++++++++++++++++++++++++++++
//    if ((numBytes <= 0) || (position >= fileLength))  // For original Nachos file system
    if ((numBytes <= 0) || (position > fileLength))  // For lab4 ...
		return 0;	

	// check request
    if ((position + numBytes) > fileLength)
		//numBytes = fileLength - position;
		hdr->ExtendSpace(position+numBytes);
//2021.11.21add++++++++++++++++++++++++++++++++++++++++	

Implemente el método OpenFile::WriteBack y realice la operación de reescritura de datos llamando al método WriteBack de filehdr

void
OpenFile::WriteBack()
{
    
    
    hdr->WriteBack(sector);
}

El último paso es eliminar el comentario delante de openfile->WriteBack() del método Append en fstest.cc como se menciona en la guía experimental.

//2021.11.21add++++++++++++++++++++++++++++++++++++++++
//  Write the inode back to the disk, because we have changed it
  openFile->WriteBack();
  printf("inodes have been written back\n");
//2021.11.21add++++++++++++++++++++++++++++++++++++++++

2. Versión de aceptación

Primero, debe implementar el método WriteBack de la clase openFile, agregar la variable miembro hdrSector para registrar el número de sector donde se encuentra el encabezado del archivo y eliminar el frente de openfile->WriteBack() en el método Append en fstest.cc como se menciona en la guía experimental.

Agregue el método WriteBack a la clase openFile en el archivo openfile.h

//lab4 add++++++++++++++++++++++++++++
void WriteBack();

Agregar variable miembro privada hdrSector

private:
	//lab4 add+++++++++++++++++++++++++++++
	int hdrSector;

Luego implemente el método WriteBack en openfile.cc

//lab4 add++++++++++++++++++++++++++++
void
OpenFile::WriteBack()
{
    
    
    hdr->WriteBack(hdrSector);
}

Inicialice la variable miembro hdrSector en el constructor de la clase openFile en el archivo openfile.cc

[Falló la transferencia de imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-leech, se recomienda guardar la imagen y cargarla directamente (img-BhJ6VjBD-1642243978465) (experimental report.assets/image-20211211200655906.png)]

Elimine el comentario antes de abrir archivo->WriteBack() en el método Agregar en fstest.cc.

//lab4 add++++++++++++++++++++++++++++
// Write the inode back to the disk, because we have changed it
openFile->WriteBack();
printf("inodes have been written back\n");

A continuación, implemente el método de extensión de archivo ExtendSpace

Agregue el método ExtendSpace a la clase FileHeader en el archivo filehdr.h

//lab4 add++++++++++++++++++++++++++++  
bool ExtendSpace(OpenFile *bitmapfile,int newSize);

Luego implemente el método ExtendSpace en el archivo filehdr.cc

//lab4 add++++++++++++++++++++++++++++
bool
FileHeader::ExtendSpace(OpenFile *bitmapfile,int newSize)
{
    
    
	//计算所需扇区
    int newNumSectors  = divRoundUp(newSize, SectorSize);
	//不需扩展,直接更新文件头信息
    if(newNumSectors == numSectors){
    
    
        numBytes = newSize; 
        return true;   
    }
	//需要扩充的扇区数量
    int diffSector = newNumSectors - numSectors;    
	
    BitMap *freeMap = new BitMap(NumSectors);
    freeMap->FetchFrom(bitmapfile);
	
	//超出一级索引||空间不足
    if(newNumSectors>NumDirect||freeMap->NumClear()< diffSector){
    
    
		return false;   
    }
	//分配新扇区,并更改文件头信息
    for(int i = numSectors; i<newNumSectors; i++)
    {
    
    
        dataSectors[i] = freeMap->Find();
    }
    numBytes = newSize;
    numSectors = newNumSectors;
    return true;
}
//lab4 add+++++++++++++++++++++++++++++++++++++++++

Finalmente, modifique la función WriteAt de la clase openFile en el archivo openfile.cc para determinar si el archivo necesita ser extendido.Si necesita ser extendido, llame al método ExtendSpace para extender el archivo.

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-leech, se recomienda guardar la imagen y cargarla directamente (img-RD72jYZx-1642243978466) (informe experimental.assets/image-20211211200428889.png)]

Supongo que te gusta

Origin blog.csdn.net/m0_47470899/article/details/122514153
Recomendado
Clasificación