理论课:https://www.bilibili.com/video/BV1d4411v7u7
有用的参考资料(linux-0.11 注释版):https://github.com/beride/linux0.11-1
main branch 为 linux-0.11 源码
改写 bootsect.s 主要完成如下功能:
改写 setup.s 主要完成如下功能:
实验指导书:https://www.lanqiao.cn/courses/115/labs/568/document/
实验指导书:https://www.lanqiao.cn/courses/115/labs/569/document/
实验指导书:https://www.lanqiao.cn/courses/115/labs/570/document/
原切换方式是通过tss,相当于是寄存器的快照,通过intel提供的指令直接进行现场替换,速度较慢。堆栈切换的效率更高。
实验指导书:https://www.lanqiao.cn/courses/115/labs/571/document/
参考:https://blog.csdn.net/qq_42518941/article/details/119182097
sem_t* sem_open(const char *name, unsigned int value);
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
int sem_unlink(const char *name);实验指导书:https://www.lanqiao.cn/courses/115/labs/572/document/
逻辑地址 -> GDT -> LDT -> 页表 -> 物理地址
由 GDTR 访问全局描述符表是通过“段选择子”(实模式下的段寄存器)完成的
15 3 2 1 0
| index | | RPL |
段选择子包括三部分:描述符索引(index)、TI、请求特权级(RPL)。它的index(描述符索引)部分表示所需要的段的描述符在描述符表的位置,由这个位置再根据在GDTR中存储的描述符表基址就可以找到相应的描述符。然后用描述符表中的段基址加上逻辑地址(SEL:OFFSET)的OFFSET就可以转换成线性地址,段选择子中的TI值只有一位0或1,0代表选择子是在GDT选择,1代表选择子是在LDT选择。请求特权级(RPL)则代表选择子的特权级,共有4个特权级(0级、1级、2级、3级)。
关于特权级的说明:任务中的每一个段都有一个特定的级别。每当一个程序试图访问某一个段时,就将该程序所拥有的特权级与要访问的特权级进行比较,以决定能否访问该段。系统约定,CPU 只能访问同一特权级或级别较低特权级的段。
例如给出逻辑地址:21h:12345678h转换为线性地址
a. 选择子 SEL = 21h = 0000000000100 0 01(b) 代表的意思是:选择子的index=4即0100,选择 GDT 中的第4个描述符;TI=0 代表选择子是在 GDT 选择;最后的01代表特权级 RPL=1。
b. OFFSET=12345678h若此时 GDT 第四个描述符中描述的段基址为11111111h,则线性地址 = 11111111h + 12345678h = 23456789h。
实验指导书:https://www.lanqiao.cn/courses/115/labs/573/document/
实验指导书:https://www.lanqiao.cn/courses/115/labs/574/document/
对机械磁盘的读写需要三个参数进行定位
block = C * (H * S) + H * S + S;将几个扇区划分为一个block来提升磁盘io效率(linux0.11 将2个扇区划分为一个block)对于更上层的角度而言,只需要输入读写的block号即可进行磁盘io。
划分: 引导块 | 超级块 | inode位图 | 数据位图 | inode块 | 数据块
用 FCB(linux0.11 中的 inode)来存储文件信息,其中包括不同种类的文件(例:设备文件,目录文件...)。
struct m_inode
{
unsigned short i_mode; // 文件类型和属性(rwx 位)。
unsigned short i_uid; // 用户id(文件拥有者标识符)。
unsigned long i_size; // 文件大小(字节数)。
unsigned long i_mtime; // 修改时间(自1970.1.1:0 算起,秒)。
unsigned char i_gid; // 组id(文件拥有者所在的组)。
unsigned char i_nlinks; // 文件目录项链接数。
unsigned short i_zone[9]; // 直接(0-6)、间接(7)或双重间接(8)逻辑块号。
/* these are in memory also */
struct task_struct *i_wait; // 等待该i 节点的进程。
unsigned long i_atime; // 最后访问时间。
unsigned long i_ctime; // i 节点自身修改时间。
unsigned short i_dev; // i 节点所在的设备号。
unsigned short i_num; // i 节点号。
unsigned short i_count; // i 节点被使用的次数,0 表示该i 节点空闲。
unsigned char i_lock; // 锁定标志。
unsigned char i_dirt; // 已修改(脏)标志。
unsigned char i_pipe; // 管道标志。
unsigned char i_mount; // 安装标志。
unsigned char i_seek; // 搜寻标志(lseek 时)。
unsigned char i_update; // 更新标志。
}; inode里存放着文件在磁盘中的 block 号,以及其他的一些文件描述信息。可以存在多级的盘块位置引导,分为直接索引、间接索引获得 block 位置。
根据 目录 inode 找到对应数据盘块号中的数据,其中有该目录下存在子目录的 inode 盘块号。一层一层查找下去就可以找到最终目标目录的位置。
实验指导书:https://www.lanqiao.cn/courses/115/labs/575/document/