/// <summary> /// 流写入 /// </summary> /// <param name="cin">待写入的流</param> /// <param name="position">写入起始位置</param> /// <param name="count">需写入的数量</param> protected void WriteStream(byte[] cin, int itemNum, int count, InodeStr dinode) { int pos = _dire.BMap(dinode, itemNum / 512); _diskFile.OpenFile(); _diskFile.SeekFilePosition(pos * 512 + itemNum % 512, System.IO.SeekOrigin.Begin); _diskFile.WriteFile(ref cin, 0, count); _diskFile.CloseFile(); }
/// <summary> /// 初始化数据块 /// </summary> public void InitDataBlock() { byte[] writeTo; _initSuper._s_nfree = 0; _initSuper._s_free[_initSuper._s_nfree++] = 0; _diskFile.OpenFile(); //从最后一块往前走,每100块之前的一块为管理块 //其内容包括 //1:该管理块管理的块数 //2:该管理块管理的所有块号 for (int i = _dataBlkNum - 1; i >= 0; --i) { if (_initSuper._s_nfree >= 100) { //找到要写入的位置,将s_nfree和s_free写入i + datablkstart号磁盘块 _diskFile.SeekFilePosition(_diskFile.ConvertPosition(i + _dataBlkStart, 0), System.IO.SeekOrigin.Begin); //转换成流,写入磁盘 writeTo = Helper.Struct2Bytes(_initSuper._s_nfree); _diskFile.WriteFile(ref writeTo, 0, 4); for (int j = 0; j < _initSuper._s_nfree; ++j) { //转换成流,写入磁盘 writeTo = Helper.Struct2Bytes(_initSuper._s_free[j]); _diskFile.WriteFile(ref writeTo, 0, 4); } _initSuper._s_nfree = 0; } //数组元素初始化(数组元素用于管理空闲块号) _initSuper._s_free[_initSuper._s_nfree++] = i + _dataBlkStart; } //关闭磁盘文件 _diskFile.CloseFile(); //将更新后的超级快信息写回 _initSuper.UpdateSuperBlockToDisk(); }
/// <summary> /// 将编译好的启动文件boot.bin按规定写入磁盘 /// </summary> public void WriteBootBlock() { int bootSize = MachinePara.Boot_Size * MachinePara.Block_Size; byte[] writeTo = new byte[bootSize]; //读取boot.bin _bootFile.OpenFile(); _bootFile.SeekFilePosition(0, System.IO.SeekOrigin.Begin); _bootFile.ReadFile(ref writeTo, 0, 512); _bootFile.CloseFile(); //写入c.img _diskFile.OpenFile(); _diskFile.SeekFilePosition(0, System.IO.SeekOrigin.Begin); _diskFile.WriteFile(ref writeTo, 0, bootSize); _diskFile.CloseFile(); }
/// <summary> /// 将编译好的内核kernel.bin文件按规定写入磁盘 /// </summary> public void WriteKernelBlock() { _kernelFile.OpenFile(); int kernelFileLength = (int)_kernelFile.ReturnFileLength(); byte[] writeTo; writeTo = new byte[kernelFileLength]; //读出kernel.bin文件的内容 _kernelFile.SeekFilePosition(0, System.IO.SeekOrigin.Begin); _kernelFile.ReadFile(ref writeTo, 0, kernelFileLength); _kernelFile.CloseFile(); //将kernel.bin的内容写入c.img _diskFile.OpenFile(); _diskFile.SeekFilePosition(1 * 512, System.IO.SeekOrigin.Begin); _diskFile.WriteFile(ref writeTo, 0, kernelFileLength); _diskFile.CloseFile(); }
/// <summary> /// 创建文件时的目录搜索 /// 本函数共4个出口 /// 出口1:目录搜索完毕,且满足三个条件:1.之前各级目录名都能找到,2.但没有符合的最后一级文件,3.且传入的flag为CREATFILE /// 出口2:目录搜索完毕,但不完全满足上述三个条件 /// 出口3:文件(或目录)在系统中已存在,且传入flag为DELETEFILE /// 出口4:文件(或目录)在系统中已存在,但传入flag不为DELETEFILE /// </summary> /// <param name="path">创建文件的目录</param> /// <param name="DirInodeNo">父目录的inode号</param> /// <returns>目录项的位置</returns> public int NameI(string path, ref int dirInodeNo, ref InodeStr dirInode, ref int fileInodeNo, ref InodeStr fileInode, ref char[] fileName, int flag) { //用于记录在路径字符串中扫描到了哪里 int curPos = 0; //用于记录inode号 dirInodeNo = 0; //首先读入根目录inode _inode.GetInodeFromDisk(dirInode, dirInodeNo); //跳过开始的一个(或者多个)'/'字符 for (; curPos < path.Length; ++curPos) { if (path[curPos] != '/') { break; } } //主循环 while (true) { //获取两个'/'当中的内容,存入dirPath中 char[] tmp = new char[28]; for (int i = 0; curPos < path.Length; ++curPos, ++i) { if (path[curPos] == '/') { break; } tmp[i] = path[curPos]; } tmp.CopyTo(fileName, 0); //跳过下一个(或者多个)'/'字符,为下一次循环(下一级目录,如果有的话)做准备 for (; curPos < path.Length; ++curPos) { if (path[curPos] != '/') { break; } } //用于存储扫描当前目录文件的偏移量 int offset = 0; //用于记录第一个空闲目录项的偏移量 int firstFreeOffset = 0; //记录是否又空闲目录项 int freeFlag = 0; //目录项项数 int dirSize = dirInode._i_size / 32; //用于读取一个磁盘块 byte[] buffer = new byte[512]; //(次循环)在当前目录文件中搜索 while (true) { //出口1:对当前目录搜索完毕(用于查找是否有同名文件存在) if (dirSize == 0) { //若当前目录索搜索完毕(没有找到相应项),且只是路径名的最后一段没有找到(要创建的文件名),则创建文件 if (flag == File.CREATFILE && curPos == path.Length) { //新分配一个inode控制块,返回该inode号 try { fileInodeNo = _inode.FetchFreeInode(); } catch (Exception ex) { Console.WriteLine(ex.Message); } //根据inode号获取对应的inode(搜索到了哪一层就获取哪一层目录的inode) _inode.GetInodeFromDisk(fileInode, fileInodeNo); //若之前扫描途中有空闲项,则返回其偏移,否则就返回当前inode的大小(即要对当前inode进行扩充) if (freeFlag == 0) { return(dirInode._i_size); } else { return(firstFreeOffset); } } //出口2:若当前目录搜索完毕(没有找到相应项),且中间路径没有找到,则出错 else { Error.ErrorType = Error.SEARCHDIR; return(-1); } } //搜索完一块,需要读入新块 if (offset % 512 == 0) { _diskFile.OpenFile(); _diskFile.SeekFilePosition(this.BMap(dirInode, offset / 512) * 512, System.IO.SeekOrigin.Begin); _diskFile.ReadFile(ref buffer, 0, 512); _diskFile.CloseFile(); } bool match = true; for (int j = 0; j < 28; ++j) { if (Convert.ToByte(fileName[j]) != buffer[offset % 512 + j + 4]) { match = false; break; } } //表示不匹配 if (!match) { dirSize--; //如果之前的目录项为空,则将其用first_free_offset标记 //+4是因为每个目录项的前四个字节是inode号 if (buffer[offset % 512 + 4] == '\0' && firstFreeOffset == 0) { firstFreeOffset = offset; freeFlag = 1; } offset += 32; continue; } //在当前目录中找到了和dirPath匹配的目录项 else { break; } } byte[] ino = new byte[4]; for (int k = 0; k < 4; ++k) { ino[k] = buffer[offset % 512 + k]; } /* 出口3: * 删除操作 * pathPoint == path.Length表示:目录项已经搜索完毕*/ if (flag == File.DELETEFILE && curPos == path.Length) { //需删除文件的inode号 fileInodeNo = (int)Helper.Bytes2Struct(ino, typeof(int)); return(offset); } /* 出口4: * 同一目录下的文件名相同,且不是要做删除操作,则出错 * pathPoint == path.Length表示:目录项已经搜索完毕*/ if (flag != File.DELETEFILE && curPos == path.Length) { Error.ErrorType = Error.SAMEFILENAME; return(-1); } //如果还有下级目录,则更新dirInodeNo与dirInode,为当前目录 dirInodeNo = (int)Helper.Bytes2Struct(ino, typeof(int)); _inode.GetInodeFromDisk(dirInode, dirInodeNo); } }
/// <summary> /// 将当前的超级快信息更新到磁盘 /// </summary> public void UpdateSuperBlockToDisk() { byte[] writeTo; //定位到超级块起始位置 _diskFile.OpenFile(); _diskFile.SeekFilePosition(MachinePara.BootAndKernelSize * 512, System.IO.SeekOrigin.Begin); //inode区占据的磁盘块数 writeTo = Helper.Struct2Bytes(_s_isize); _diskFile.WriteFile(ref writeTo, 0, 4); //总的磁盘块数,为扇区数的一半 writeTo = Helper.Struct2Bytes(_s_fsize); _diskFile.WriteFile(ref writeTo, 0, 4); //得到直接管理块数 writeTo = Helper.Struct2Bytes(_s_nfree); _diskFile.WriteFile(ref writeTo, 0, 4); //得到空闲列表 for (int i = 0; i < 100; ++i) { writeTo = Helper.Struct2Bytes(_s_free[i]); _diskFile.WriteFile(ref writeTo, 0, 4); } //得到直接管理的inodee数量 writeTo = Helper.Struct2Bytes(_s_ninode); _diskFile.WriteFile(ref writeTo, 0, 4); //得到空闲inode列表 for (int i = 0; i < 100; ++i) { writeTo = Helper.Struct2Bytes(_s_inode[i]); _diskFile.WriteFile(ref writeTo, 0, 4); } //封锁标志 writeTo = Helper.Struct2Bytes(_s_flock); _diskFile.WriteFile(ref writeTo, 0, 4); //inode封锁标志 writeTo = Helper.Struct2Bytes(_s_ilock); _diskFile.WriteFile(ref writeTo, 0, 4); //已修改标志 writeTo = Helper.Struct2Bytes(_s_fmod); _diskFile.WriteFile(ref writeTo, 0, 4); //只读标志 writeTo = Helper.Struct2Bytes(_s_ronly); _diskFile.WriteFile(ref writeTo, 0, 4); //最后修改时间 writeTo = Helper.Struct2Bytes(_s_time); _diskFile.WriteFile(ref writeTo, 0, 4); //填充字段 if (_s_padding[0] == 1) { for (int i = 0; i < 47; i++) { writeTo = Helper.Struct2Bytes(_s_padding[i]); _diskFile.WriteFile(ref writeTo, 0, 4); } _s_padding[0] = 0; } _diskFile.CloseFile(); }