日期:2022-10-09
版本号:V1.0
作者:snow
一、基础概念
1.1 内核进程关系
引导程序为进程0在32位保护模式下得运行创建了相应得条件,使进程0能够依靠主机进行相关运行;而进程1在进程0的基础上加载了文件系统,使得进程1能够通过文件与外设进行数据交互;进一步,进程2在进程1的基础上构建了一套人机交互界面,使得用户能够与计算机进行交互,并最终进入怠速状态(同时成为用户进程的母本)
1.2、i节点
linux中任何一个文件或者目录都是作为文件存在,一个文件的基本属性和存储位置都通过其i节点进行体现。(其中连接数为原件+硬连接次数)。而要获得文件的i节点信息,就必须通过文件所在存储设备的设备号及该节点的节点编号。若有相对路径名称或者绝对路径名称,则分别从当前所处节点或根节点进行扫描搜索。
文件的字节数
文件拥有者的User ID
文件的Group ID
文件的读、写、执行权限
文件的时间戳,共有三个:ctime指inode上一次变动的时间,mtime指文件内容上一次变动的时间,atime指文件上一次打开的时间。
链接数,即有多少文件名指向这个inode
文件数据block的位置
二、加载根文件系统
2.1、硬盘加载
2.1.1 结构化硬盘参数
在第三篇章的2.1节中备份了硬盘的基本参数,将这些参数复制相应的结构体中便于管理,例如hd_info[i].cyl head wpcom ctr lzone sect对应硬盘引导等参数(主要目的是为了便于通过函数进行硬盘的读写操作)。
2.1.2 读取硬盘引导块
将硬盘的的第0号逻辑块(即第0、1两个扇区,1KB)的内容读取到缓冲区中。
- 获取硬盘的缓冲块(先通过哈希表查找是否已经存在,若没有,则从链表中申请,并标记相应的哈希表)
- 对缓冲块进行配置(数量、起始位置、对应设备的编号等)
- 将缓冲块与请求项
- 检查硬盘设备是否存在以及块设备(硬盘)的请求函数是否有效,若无效则退出
- 将缓冲块的读请求加入到请求项队列中
- 缓冲块上锁
- 初始化请求项结构(对应设备号、读写命令、操作逻辑块位置数量等)
- 将请求项结构加入到硬盘请求函数中(如果硬盘当前没有其他请求)
- 处理硬盘请求(根据请求项以及hd_info中的信息解析除磁头、扇区、柱面以及扇区数量等信息)
- 发起读取命令(以回调方式读取)
- 等待读取完成(通过缓冲块是否上锁判断,进程1被挂起)
- 第一个扇区读取完成,硬盘中断触发回调读取回调,从硬盘数据寄存器端口读取256个字(512字节)到缓冲块的缓冲区中,待读取扇区数量减1(从2变为1),未读取完成,将当前请求项继续作为硬盘读取请求。
- 第二个扇区读取完成,硬盘中断触发回调读取回调,从硬盘数据寄存器端口读取256个字(512字节)到缓冲块的缓冲区中,待读取扇区数量减1(从1变为0),当前请求项执行完毕,将缓冲块标记未可用状态,并解锁。
- 进程1恢复至就绪状态
2.1.3 解析硬盘分区
(1)验证引导块内容(判断第一个扇区的最后两个字节是否为0X55AA)
(2)从引导块中获取分区信息(数量、起始位置等)
(3)释放缓冲块
2.2、软盘加载
默认软盘为根设备
2.2.1 预读取软盘引导块
(1)将软盘的256~258的三个数据块读出,其中优先读出超级块257(步骤参考2.1.2)
(2)将超级块的信息备份到进程1栈中
(3)释放超级块
2.2.2 解析软盘分区
(1)验证引导块内容(判断第一个扇区的最后两个字节是否为0X55AA)
(2)从超级块中的信息获取根文件系统数据块信息(数量、起始位置等)
(3)验证虚拟盘空间是足够
2.3、虚拟磁盘加载
(1)申请缓冲块
(2)将软盘中根文件系统的相应数据数据块拷贝至虚拟盘所在内存中
(3)释放缓冲块
(4)将虚拟盘作为新的根设备
2.4、加载根文件系统
2.4.1 文件管理表初始化
将文件表中的所有文件使用次数清0
2.3.4 设备超级块初始化
linux定义了一定数量(8)的超级块,每个超级块可对应一个设备,若主机需要以文件的形式与设备进行数据交互,则必须通过对应超级(根设备也在此列,故必需初始化这些超级)。超级块的基本信息初始化(是否挂载、是否只读、是否可用等)
由于超级块中部分数据(根目录i节点和逻辑位图)还没有加载,故需要加锁。
2.3.5 加载根文件系统超级块
(1)读取根设备的超级块至缓冲块(若已读取,直接使用)
(2)将根设备的超级块从缓冲块拷贝至内核空间
(3)释放缓冲块
(4)验证超级块魔数
(5)从虚拟盘中读取i节点位图管理结构和逻辑位图管理结构
(6)将i节点位图和逻辑位图管理结构绑定到超级块中
(7)超级块解锁
2.3.6 加载根节点
(1)从inode_table中申请一个空闲节A点
(2)空闲节点A初始化(节点号、设备号、上锁)
(3)从虚拟盘中读取根节点所在得逻辑块号
(4)提起根节点的信息,将其解析到节点A中
(5)释放读取过程中的缓冲块,并对节点A解锁
(6)将文件系统的根目录设置为节点A(一个电脑所有设备只有一个根节点)
(7)将超级块的安装节点设置为节点A(每个设备都有一个自己的节点)
(8)超级块逻辑位图占用更新(根设备超级块初始化完成,可用)
三、打开终端设备文件
主要是打开/dev/tty0文件
3.1、确定目录i节点
(1)由于第一个字符为’/’,故将当前inode为根i节点
(2)获取下一级目录名称dev(通过第二个’/’判断)
(3)获取取inode节点下的dev目录项(包括dev的设备号和i节点号)
(4)根据dev的设备号和i节点号获取dev的i节点
(5)重复步骤2,名称为tty0,同时后续无‘/‘字符,返回该文件的目录i节点
3.2、确定文件i节点
(1)确定文件的相对名称
(2)通过目录的i节点,文件名称获取tty0的文件项(包括tty0的设备号和i节点号)
(3)根据tty0的设备号和i节点号获取tty0的i节点
3.3 文件节点结构初始化
(1)检查该节点是否可用
(2)初始化访问时间
(3)解析tty0的i节点属性(字符设备类型,设备号-含主次)
(4)将tty0的次设备号作为进程1当前使用的tty设备号
(5)将tty0的归属组设置为当前组
(5)将tty0的i节点信息连接file_table表中,同时在该表中将tty0使用次数标记为1
3.4 复制文件句柄
(1)将内核的file_table表关于tty0的信息复制到当前进程的filep中,并将使用次数加1(作为标准输入输出设备使用)。
(2)再次将内核的file_table表关于tty0的信息复制到当前进程的filep中,并将使用次数加1(作为标准错误输出设备使用)
四、创建进程2
与进程0创建进程1相似
- 当前寄存器压栈
- 申请空闲进程,并阻塞进程
- 拷贝进程信息
- 申请空闲页面
- 复制页面与页目录表(由160改为1024)
- 激活进程2的页目录表
- 挂接LDT与GDT
- 启动进程2
- 等待进程2结束