《操作系统真象还原》13章编写硬盘驱动程序


这一章比较繁琐都是底层的东西,首先我们得先弄清楚这一章要做什么?

  1. 创建副盘完成分区,用于安装文件系统
  2. 编写硬件驱动程序,给操作系统提供硬盘的更好用的封装了的接口

哈哈分析下来这一章就做了两件事而已,但是大家可别小瞧这两件事,因为硬盘太底层了,封装硬件接口需要不少的底层知识。大伙加油~

创建副盘完成分区

先了解一些理论知识吧:

  • MBR、EBR、OBR、DBR是什么?

这上面的概念如果不理解的话就看第0章吧,那里有比较好的解释,但在此我们主要要理清,MBR和EBR实际上是相同的概念,只不过用于不同的地方。MBR保存着整个副盘的分区表信息,最多只有4个分区,然后因为要扩大分区,引入了逻辑分区的概念

  • 逻辑分区的意思就是:将原来的四个分区中的某一个分解成多个**”硬盘“**
  • 那么这些**”硬盘“** 要和物理硬盘结构一样,所以引入EBR当成“硬盘”的MBR ,保存着这些“硬盘”中的分区信息。
  • 所以这个**“硬盘”** 理论上来说是可以无限套娃的,咱们又可以在里面找一个来做逻辑分区,这样就可以让分区足够多了。
  • 分区完之后的结果如下图所示image-20210917155259368

或许你注意到了上图的Start是从2048而不是1开始的,也就是说前面预留了1MB(2048*512B)的空间,我百度了一下,发现这是2011年后高度格式化的硬盘开始普及,(并且这时候操作硬盘的最小单位已经是4KB了)这1MB需要放grub2需要的一些启动信息,也就是说已经不是咱们学的单单利用MBR来启动了,具体是怎么样的。哈哈我也不太清楚。而且分区与分区之间还有了间隔,也是要存一些信息吧。只要我们知道这些位置就好啦。

怎么创建副盘和分区呢

哈哈,这个我已经写好脚本了,直接按下面步骤,复制代码(记得改一下代码中路径path)到de8里面之后运行de8即可

image-20210917150950041

分完区之后,你可以执行一下 ,下面这行,就可以得到分区结果啦

cfdisk hd80M.img  
# !/bin/bash

path="/home/linxi/bochs/bin"  #bin 
cd $path
rm hd80M*
echo -e "1\nhd\nflat\n80\nhd80M.img\"|./bximage 
echo -e "x\n\
c\n\
162\n\
h\n\
16\n\
r\n\
n\n\
p\n\
1\n\
\n\
32\n\
n\n\
e\n\
4\n\
\n\
\n\
n\n\
\n\
50\n\
n\n\
\n\
75\n\
n\n\
\n\
100\n\
n\n\
\n\
125\n\
n\n\
\n\
\n\
t\n\
5\n\
66\n\
t\n\
6\n\
66\n\
t\n\
7\n\
66\n\
t\n\
8\n\
66\n\
t\n\
9\n\
66\n\
w\n" | fdisk -u=cylinders ./hd80M.img

编写硬盘驱动程序

咱们既然是要管理硬盘,并提供更高的接口,那么首先得设计出表示硬盘的这种数据结构

咱们操作硬盘是得通过通道来访问的,一个通道有两个硬盘

  1. 硬盘也是外设,访问外设就要**通过中断,**所以也得把硬盘的中断打开
  2. 按照实际结构,定义出表示硬盘、分区、ata通道结构的结构体
  3. 实现thread_yield,用于让出CPU,比如访问硬盘时主动让出CPU
  4. idle线程,用于挂起CPU(阻塞当前进程,执行hlt)

描述硬盘所需要的数据结构

这个操作系统中住上上只有两个通道

  • 通道1范围 0x1F0 - 0x1F7 , 控制块寄存器为 0x3F6
  • 通道2范围0x170 - 0x1f7 ,控制块寄存器为 0x376

数据结构包括: 硬盘、分区、通道,都是结构体按照功能实现即可。

硬盘的读写过程

建好数据结构之后,实际上就只有两种操作:读和写,在对硬盘的读写中

磁盘操作的具体过程有比较好的博主给出了详细的过程,大家可以参考一下https://www.jianshu.com/p/c0d0f192a7f9,在此过程中要清楚,CPU控制所谓的硬盘控制器(通道)实际上就是赋值给指那几个控制器中的寄存器。下面我给出具体原理:

cpu要想直接访问设备里的数据,必须对设备存储空间进行编址。而硬盘数据数据太大,直接编址数据线成本太高,于是设计上在这类设备和总线之间加了一个控制器。这个控制器里有少量寄存器可以被cpu访问,而这个控制器又能控制硬盘驱动器读写数据,所以,cpu通过对硬盘控制器里的少量io寄存器的读写来控制对整个硬盘的读写。cpu告诉磁盘控制器读哪些地址的数据,磁盘控制器读好之后放入能被 cpu访问的数据寄存器中,再将这里的数据传给内存。

建好数据结构之后整个硬盘的读取大致就是这么一个过程。

image-20210921095128800

下面是硬盘的写入

image-20210921101447127

实现细节

打开从片上的IRQ14

创建分区、硬盘、通道结构,关系是:一共通道有两个硬盘,一个硬盘最多有4个分区

超级块指针 super_block * 只是一个用来占位的,因为还没有实现,文件系统的时候会实现

或许硬盘数量之后,初始化相应的通道。通道每次都只能访问一个硬盘,因此的加上通道lock

下面是新加的函数及其作用

  • select_disk 选择读写的硬盘

  • cmd_out 通道channel发命令cmd

  • write2sector 将buf中sec_cnt 扇区的数据写入硬盘

  • busy_wait 等待30秒

  • ide_read 从硬盘读取sec_cnt个扇区到buf

  • ide_write 将buf中sec_cnt 扇区数据写入硬盘

  • intr_hd_handler 硬盘中断处理程序

  • ide_init 硬盘数据结构初始化

  • ext_lba_base 用于记录总扩展分区的起始lba,初始位0,partition_scan时以此为标记 用sys_malloc,一个栈 + PCB 只有4096个字节

  • partition_scan(struct disk* hd, uint32_t ext_lba)扫描硬盘hd中地址为ext_lba的扇区中的所有分区 如果ext_lba_base为0代表是第一次扫

  • struct list partition_list; // 分区队列

  • partition_table_entry 分区表项

  • swap_pairs_bytes(const char* dst, char* buf, uint32_t len) 将dst中len个相邻字节交换位置后存入buf

  • identify_disk(struct disk* hd) 获得硬盘参数信息

  • partition_info 打印分区信息

细节

attribute ((packed)); // 保证此结构是16字节大小

image-20210917134623096

运行结果

image-20210917160630069

64位makefile一键修改

https://blog.csdn.net/qq_45923646/article/details/120273571

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值