I/O与显示器


用统一的接口进行操作:
- 接口如下 :open()、read()、write()、close()

主要就是write(1,buf,…)中的参数1在发挥作用,如下:
- 将fd = 1,传递
- filp(文件打开表),即找到filp中的第一项
- 所以file = 当前进程PCB中的文件中的filp数组中的第一项
- 取出file的f_inode这个信息给inode
file = current->filplfd]; //当前进程
所有文件的打开文件的指针都是父进程拷贝来的

先是初始化出了进程0 ,随后进程0又拷贝了进程1,再通过进程1进而找到
void init(void){
open("dev/tty0",O_RDWR,0); dup(0); dup(0); //这里tty就是中断设备,并且拷贝了两个进程,即 进程0 和 进程1 ,都是从tty0拷贝的,
execve("/bin/sh",argv,envp)
}

通过那个 1 来找到dev/tty0中的inode,inode在磁盘中存放的信息就可以使系统知道是给屏幕显示还是其他设备操作

- 首先查看是否是CHR 设备
- 读写rw_char函数,传入参数是 WRITE(写) ,还要知道是哪一个设备。即通过inode设备知道是字符设备的第几个设备
- 这里是第四个设备,第0个从设备
- crw_table : 函数指针 ,下一行代码就是对传入对应的参数

写是在显示器写,读是把键盘的读出
一开始传入的参数就是write,在上图最后的sleep_if_full 则是往缓冲区中写,而不是直接显示在显示器上,缓冲区满了就等待一会再发数据,平衡cpu和内存之间的速度差距

往缓冲区中写数据,满了就开始用tty-write 开始读

con_write 函数 == console_write ,即终端显示
从write_q中取出一个字符 c, ax = ah + al ,现在ah = movb_attr(字符属性),al = 字符c
科普:
- 计算机外设如果是 独立编制时用,out指令
- 计算机外设如果是 统一和内存编址,用mov指令


两个字符 = 属性 + 字符本身
printf整个过程

键盘





总结:
生磁盘的使用
磁盘硬件

- CPU向磁盘控制器中的寄存器读写数据
- 磁盘控制器完成真正的工作,并向CPU发中断信号
认识磁盘


磁盘中断请求函数

- do_hd_request 磁盘的请求函数
- out命令用来输出磁盘上的数据
各个参数是需要移动的,拼凑成一个数据进行操作磁盘

- 把一维地址抽象为三维地址 (这样就可以通过一个地址知道三个数据,即CHS)
CHS第一层抽象过程

b取余sector得s,b除sector得ch+h,b除hs等于c,ch+h-ch得到h
用空间利用率的下降换取读写速度的大幅提升,直接读一个盘块block,而不是扇区

注意上图旁边批注!
Linux0.11的盘块 = 1k
- 一个扇区512

多个进程通过队列使用磁盘(第二层抽象)
FCFS先来先服务

问题:来回时间跨度太大了
SSTF近点调度

上述问题:磁盘中间频率高,一些进程会 — 饥饿

算法的升级:每个请求都可执行,但是中间的请求还是占便宜了
C-SCAN磁盘调度(电梯算法)

左边探寻完右边直接到头复位,中间和两边是公平的
多个进程共同使用磁盘(源码)


红色部分:
...reg->sector = bh->b_blocknr<<1; //根据用户盘块号转换扇区号将add_request这个请求加入队列
- 因为是多个进程共享的,所以需要关中断 cli()
中间的 if 语句就是实现电梯队列的效果
最后的 IN_ORDER 函数就是比较 s1 和 s2 大小的
总结

- 知道盘块号 –> 算出扇区号
- 用扇区号建立请求,用
电梯算法将缓冲区加载到请求队列中 - 进程就可以睡眠了,剩下的都是磁盘硬件的工作
- 磁盘中断处理请求队列中的请求
- 用do_hd_request 磁盘驱动 算出sec(扇区)、head(磁头)、cyl(柱面),用out指令传输给磁盘控制器
- 工作完成后再次进入中断请求,end_request 置1 表示结束请求
- 此时唤醒进程,得知内存中已经有了自己需要的数据
从生磁盘到文件
顺序存储


链式结构


索引结构 Index

本质还是链表的形式结构,但使用了一个文件存储其链表顺序

- 可以表示很大的文件
- 很小的文件高效访问
- 中等大小的文件访问速度也不慢!
文件使用磁盘的实现

-
fd : 文件描述符
-
buf : 文件缓冲区
-
count : 字符个数





- 通过文件名找到inode ,或者通过文件路径找到inode
- 根据inode找到盘块号
- 根据盘块号往电梯队列中放
- 根据电梯队列中的盘块号算出CHS
- 根据out发在磁盘控制器上

下图没听懂

目录与文件系统


这节就是要形成上述的体系
目录


得到文件的FCB就知道了文件的iNode,知道 iNode 和 文件位置 就能知道盘块,随后利用盘块就可以放入 电梯队列 中,有电梯队列就在磁盘中断的中用盘块算出CHS,控制器通过CHS控制马达找到数据

根目录是固定的,即初始化时固定在磁盘上的,通过根目录的FCB找到var,my的文件名以及对应FCB数组的位置(13、82),通过位置再次去FCB数组中找到自己对应的数据,有点像fork(),分叉实现树图

- 首先是init引导块
- 随后是超级块,超级块知道自己的大小以及i节点位图 大小 和 盘块位图 大小
- 知道 i节点 的初始位置就能初始化根目录 ( / )
- 有根目录就能初始其他的目录

目录解析代码实现

上节说的循环那部分的代码实现 : 如下


- 挂在第一个驱动器(硬盘):&drive_info
- 挂在硬盘的时候就会挂载根目录
- 根目录就有了









