文章目录
这一章比较繁琐都是底层的东西,首先我们得先弄清楚这一章要做什么?
- 创建副盘完成分区,用于安装文件系统
- 编写硬件驱动程序,给操作系统提供硬盘的更好用的封装了的接口
哈哈分析下来这一章就做了两件事而已,但是大家可别小瞧这两件事,因为硬盘太底层了,封装硬件接口需要不少的底层知识。大伙加油~
创建副盘完成分区
先了解一些理论知识吧:
这上面的概念如果不理解的话就看第0章吧,那里有比较好的解释,但在此我们主要要理清,MBR和EBR实际上是相同的概念,只不过用于不同的地方。MBR保存着整个副盘的分区表信息,最多只有4个分区,然后因为要扩大分区,引入了逻辑分区的概念
- 逻辑分区的意思就是:将原来的四个分区中的某一个分解成多个**”硬盘“**
- 那么这些**”硬盘“** 要和物理硬盘结构一样,所以引入EBR当成“硬盘”的MBR ,保存着这些“硬盘”中的分区信息。
- 所以这个**“硬盘”** 理论上来说是可以无限套娃的,咱们又可以在里面找一个来做逻辑分区,这样就可以让分区足够多了。
- 分区完之后的结果如下图所示
或许你注意到了上图的Start是从2048而不是1开始的,也就是说前面预留了1MB(2048*512B)的空间,我百度了一下,发现这是2011年后高度格式化的硬盘开始普及,(并且这时候操作硬盘的最小单位已经是4KB了)这1MB需要放grub2需要的一些启动信息,也就是说已经不是咱们学的单单利用MBR来启动了,具体是怎么样的。哈哈我也不太清楚。而且分区与分区之间还有了间隔,也是要存一些信息吧。只要我们知道这些位置就好啦。
怎么创建副盘和分区呢
哈哈,这个我已经写好脚本了,直接按下面步骤,复制代码(记得改一下代码中路径path)到de8里面之后运行de8即可
分完区之后,你可以执行一下 ,下面这行,就可以得到分区结果啦
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
编写硬盘驱动程序
咱们既然是要管理硬盘,并提供更高的接口,那么首先得设计出表示硬盘的这种数据结构
咱们操作硬盘是得通过通道来访问的,一个通道有两个硬盘
- 硬盘也是外设,访问外设就要**通过中断,**所以也得把硬盘的中断打开
- 按照实际结构,定义出表示硬盘、分区、ata通道结构的结构体
- 实现thread_yield,用于让出CPU,比如访问硬盘时主动让出CPU
- idle线程,用于挂起CPU(阻塞当前进程,执行hlt)
描述硬盘所需要的数据结构
这个操作系统中住上上只有两个通道
- 通道1范围 0x1F0 - 0x1F7 , 控制块寄存器为 0x3F6
- 通道2范围0x170 - 0x1f7 ,控制块寄存器为 0x376
数据结构包括: 硬盘、分区、通道,都是结构体按照功能实现即可。
硬盘的读写过程
建好数据结构之后,实际上就只有两种操作:读和写,在对硬盘的读写中
磁盘操作的具体过程有比较好的博主给出了详细的过程,大家可以参考一下https://www.jianshu.com/p/c0d0f192a7f9,在此过程中要清楚,CPU控制所谓的硬盘控制器(通道)实际上就是赋值给指那几个控制器中的寄存器。下面我给出具体原理:
cpu要想直接访问设备里的数据,必须对设备存储空间进行编址。而硬盘数据数据太大,直接编址数据线成本太高,于是设计上在这类设备和总线之间加了一个控制器。这个控制器里有少量寄存器可以被cpu访问,而这个控制器又能控制硬盘驱动器读写数据,所以,cpu通过对硬盘控制器里的少量io寄存器的读写来控制对整个硬盘的读写。cpu告诉磁盘控制器读哪些地址的数据,磁盘控制器读好之后放入能被 cpu访问的数据寄存器中,再将这里的数据传给内存。
建好数据结构之后整个硬盘的读取大致就是这么一个过程。
下面是硬盘的写入
实现细节
打开从片上的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字节大小
运行结果
64位makefile一键修改
https://blog.csdn.net/qq_45923646/article/details/120273571