dos虚拟机

  本程序用mingw developer studio 2.05编译,由于本人水平有限,程序难免会有很多不足
  由于涉及到位移,所以本程序只为小端方式的cpu设计

  本程序4千多行代码
  我的函数一般是执行成功就返回0,否则返回-1
hdd.c模块:
  本程序和真实的dos不同,只有一个隐藏扇区就是虚拟硬盘(vhdd文件)的前512个字节,下面说到的隐藏扇区都指这个,在我的程序里扇区的概念比较简单就是512个字节,你可以把虚拟硬盘抽象成一个三维数组,比如我要找1/1/2扇区,就是数组的第[1][1][2]个元素,所以看到sec_to_bytes(PTR p)的实现就很好理解了,那里我是在求数组某元素对数组首地址的偏移量(还是上面的例子1/1/2扇区的偏移量为1 * (一个柱面的最大磁道数 + 1) * (一个磁道的最大扇区数 + 1) * 扇区字节数 + 1 * (一个磁道的最大扇区数 + 1) * 扇区字节数 + 2 * 扇区字节数)的基础上提取了公因式,真实的扇区分为扇区头,数据域(通常为512字节,一个扇区也可以不为512字节)和校验值
  因为百度找不到fat12分区的详细资料所以我保留了fat12分区,fat16分区最小9mb,fat32分区最小33mb,在这里有必要说一下我的虚拟硬盘的分区结构,跟真实的分区一样也是分为主分区和逻辑分区,逻辑分区是一张链表因为有且只可以有一个扩展分区所以只有一张链表,不要把逻辑分区跟主分区混淆了,主分区是隐藏扇区boot loader之后的64个字节是数组,一个分区表项(struct dpent_t)16个字节所以最多有4个主分区,说重点了,我推荐不要频繁的添加和删除逻辑分区,因为我是用malloc的原理来写的,你也知道太频繁的用malloc不是问题,问题是每次malloc申请的大小都不同的话就会留下很多内存碎片导致最后malloc失败了,内存碎片太多了狠一点的解决方法就是重启系统,同样如果硬盘碎片太多了狠一点的解决方法就是重建扩展分区,主分区的硬盘碎片问题就比较少因为它会灵活的伸缩
  PTR 是我自己定义的指针类型,他存储的就是扇区号,(在hdd.h里定义CHS_M)chs模式的寻址只支持小于528mb的硬盘,大于528mb只能用(在hdd.h里定义LBA_M)lba模式(线性的),由于我只找到chs模式的分区表结构体所以只为chs设计
  由于时间关系,本来startup()应该检查上次是否正常关机了,如果没有应该用第二张fat表来还原第一张fat表,方法我也想好了,由于fat表的第0个表项总是保留着的那么就可以利用它,每次开机就在那里写进去1然后关机前就把那里清0,如果上次突然断电了那么那里肯定为1那么就要实施上面说到的东西
list.h模块:
  又是链表内存的链表,因为每个函数的语句比较少所以我把他写成内联函数,为了方便吧程序一运行就会把各个分区的信息(struct fat_vr_t)加入到链表
fat_fs模块:
  这里就没什么好说的,因为里面的io函数是模仿库函数来写的,没用过的话百度一下吧,还是想到一点东西唠叨一下,我的内核函数大多数都用了goto,虽然说goto会破坏程序的结构化,可是我只是用goto来处理出错允许我使用,目录是一种树形的结构
cmd.c模块:
  我的cmd有语法检查的功能,parse函数用struct piped_t来实现的,现在打开cmd.h,也就是结构体的token成员就是&或|或<或>,num就是这个token出现的次数,举个例子token是|,num是3,那么记录的管道符就是|||,这个是错的所以就会goto parse_error,由于时间关系就没有做语义检查的功能了
  语法检查通过之后就是do_cmd,因为这几个管道c语言可以很容易的实现,举个例子,pause && cls,pause 和 cls 是2个已经写好的函数,那么就可以return pause() && cls(),如果是pause && cls || echo c & type ...呢?,就没那么理想了,所以我借助了队列(fifo)这种数据类型来实现,我把每个管道(q item)写成函数,但是要怎么记住每个简单命令(dos的内部命令就是简单命令)的返回值呢?我保存在value这个变量里
  接着就是do_list,出队列,先进先出,执行命令行的所有管道,厄...如果只是一个简单命令我是用&来执行的and函数,l_and函数就是&&,flow函数就是|,l_or函数就是||,dup2_in就是<,dup2_out就是>,dup2_out_ap就是>>
  支持管道&,&&,|,||,<,>,>>,不支持goto(方法我想好了,就是把每一个列表(一行就是列表)加入到链表然后编号就可以实现跳转了)和接受参数,for,if(也可以像上面一样把这2个写成函数好让do_cmd可以加入到队列)
  由于时间关系我的dos的内部命没有写扩展功能,同一目录下不可以有相同的文件名,不可以执行exe文件和脚步(有兴趣的可以把cmd的输入重定向到到.bat文件就可以实现)
q.c模块:
  队列,cmd的实现借助了队列
MAT.h模块:
  当程序运行时会在当前目录下生成memtrace.log文件,这个文件记录内存的使用状况(malloc分配的内存),让你看一下有没有内存泄露,如果忘记释放了,end_trace()会把它释放了,用断言的思想,当我们调试好了没有内存泄露了就在MAT.h里定义NDEBUG然后把MAT.c从工程移走
main.c模块:
  主函数写出整个程序的框架,所以应该先看主函数(main.c)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值