哈工大操作系统-4-设备驱动与文件系统
本文最后更新于293 天前,其中的信息可能已经过时,如有错误请发送邮件到cishaxiatian@gmail.com

I/O与显示器

26_1
26_2

用统一的接口进行操作:

  1. 接口如下 :open()、read()、write()、close()
26_3
26_4

主要就是write(1,buf,…)中的参数1在发挥作用,如下:

  1. 将fd = 1,传递
  2. filp(文件打开表),即找到filp中的第一项
  • 所以file = 当前进程PCB中的文件中的filp数组中的第一项
  1. 取出file的f_inode这个信息给inode
file = current->filplfd];   //当前进程

所有文件的打开文件的指针都是父进程拷贝来的

26_5

先是初始化出了进程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)
}
26_6

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

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

写是在显示器写,读是把键盘的读出

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

26_9

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

26_10

con_write 函数 == console_write ,即终端显示

从write_q中取出一个字符 c, ax = ah + al ,现在ah = movb_attr(字符属性),al = 字符c

科普

  • 计算机外设如果是 独立编制时用,out指令
  • 计算机外设如果是 统一和内存编址,用mov指令
26_11
26_12

两个字符 = 属性 + 字符本身

printf整个过程

26_13

键盘

27_1
27_2
27_3
29_4
27_5

总结

27_6

生磁盘的使用

磁盘硬件

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

认识磁盘

28_2
28_3

磁盘中断请求函数

28_4
  • do_hd_request 磁盘的请求函数
  • out命令用来输出磁盘上的数据

各个参数是需要移动的,拼凑成一个数据进行操作磁盘

28_5
  • 一维地址抽象为三维地址 (这样就可以通过一个地址知道三个数据,即CHS)

CHS第一层抽象过程

28_6

b取余sector得s,b除sector得ch+h,b除hs等于c,ch+h-ch得到h

用空间利用率的下降换取读写速度的大幅提升,直接读一个盘块block,而不是扇区

28_7

注意上图旁边批注!

Linux0.11的盘块 = 1k

  • 一个扇区512
28_8

多个进程通过队列使用磁盘(第二层抽象)

FCFS先来先服务

28_9.png

问题:来回时间跨度太大了

SSTF近点调度

28_10

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

28_11

算法的升级:每个请求都可执行,但是中间的请求还是占便宜了

C-SCAN磁盘调度(电梯算法)

28_12

左边探寻完右边直接到头复位,中间和两边是公平的

多个进程共同使用磁盘(源码)

28_13
image-20240909125236050

红色部分:

...reg->sector = bh->b_blocknr<<1;
//根据用户盘块号转换扇区号

将add_request这个请求加入队列

  • 因为是多个进程共享的,所以需要关中断 cli()

中间的 if 语句就是实现电梯队列的效果

最后的 IN_ORDER 函数就是比较 s1 和 s2 大小的

总结

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

从生磁盘到文件

顺序存储

29_1
29_2

链式结构

29_3
29_4

索引结构 Index

29_5.png

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

29_6.png
  • 可以表示很大的文件
  • 很小的文件高效访问
  • 中等大小的文件访问速度也不慢!

文件使用磁盘的实现

30_1
  • fd : 文件描述符

  • buf : 文件缓冲区

  • count : 字符个数

30_2
30_3
30_4
30_5
30_6
  1. 通过文件名找到inode ,或者通过文件路径找到inode
  2. 根据inode找到盘块号
  3. 根据盘块号往电梯队列中放
  4. 根据电梯队列中的盘块号算出CHS
  5. 根据out发在磁盘控制器上
30_7

下图没听懂

30_8

目录与文件系统

31_1
31_2

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

目录

31_3
31_4

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

31_5

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

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

目录解析代码实现

image-20240909182138020

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

image-20240909182157335
image-20240909182415871
  • 挂在第一个驱动器(硬盘):&drive_info
  • 挂在硬盘的时候就会挂载根目录
  • 根目录就有了
image-20240909183220713
image-20240909183619999
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇