哈工大操作系统
这是笔者2024.7大二升大三的暑假根据B站李治军老师的课程视频https://www.bilibili.com/video/BV19r4y1b7Aw/?p=1制作的学习笔记,但是听了两章节后感觉学习效果不是很好,所以果断弃坑(这也是笔记只有两个章节的原因),买了**《操作系统原理、实现和实践》**这本书(也是李老师课程的配套教材)来看,感觉确实比听网课效果好很多。那本书也比较薄,适合新手拿来入门。
下面就是我笔记的所有内容了,应该也不会再更新了(悲)。
1.1什么是操作系统
1.2揭开钢琴的盖子
图灵机,通用图灵机,冯诺依曼存储程序思想
取指,执行;取值,执行……
打开电源,pc指向哪里?
引导扇区:开机后执行的第一段程序
bootsect.s:汇编代码——汇编可以严格确定执行的内容
1.3操作系统启动
setup:完成OS启动前的设置
获得计算机的一些基础的参数:扩展内存数、显卡参数
ip,cs:
把16位机转换为32位机
gdt:global desciption table
linux:make file——控制编译出来的文件结构
前两节讲述的所有内容:
- boot:将操作系统从磁盘中读入
- setup:获得了一些参数,启动了保护模式(16位 - 》32?)
- head:初始化了GDT表和一些页表
- main:很多init函数,包括mem_init()等等
- mem_init:
1.4操作系统接口
用户如何使用计算机:
- 命令行
- 图形按钮
- 应用程序
命令行:
shell也是一段程序:即bin/sh
图形按钮(Linux0.11没有):消息框架程序 + 消息处理程序
接口:系统调用
1.5系统调用的实现
为什么不能让用户程序直接进入内核访问数据?而是需要借助操作系统?
- 不可以随意jump,move,否则会带来安全性的问题
将内核程序和用户程序隔离:
- 内核态可以访问任何数据,用户态不能访问内核数据
- 对于指令跳转也一样实现了隔离
DPL存放在GDT表中
硬件提供了“主动进入内核的方法”:
从printf到sys_write:
1.6操作系统历史
- 多道程序:作业之间的切换和调度成为核心:既有IO任务,又有计算任务,需要让CPU忙碌——代表:IBM OS/360
- 从OS/360到MULTICS:分时系统,核心仍然是任务切换,虚拟内存就是一种复用
- 从MULTICS到UNIX:简化的MULTICS
- 从UNIX到Linux
操作系统的核心思路:
- 多进程图谱:CPU,内存
- 、文件操作视图:I/O,磁盘
1.7我们的任务
2.1CPU管理的直观想法
管理CPU最直接的方法:设置好PC的初值
多道程序、交替执行
一个CPU上交替地执行多个程序:并发
引入“进程”概念:
- 运行的程序(进行中的程序)和静态程序(存放在磁盘中的程序)不一样
- 所有的不一样都存放在PCB中
2.2多进程图像
多进程从启动开始到关机结束
main中的fork()创建了第一个进程
- init执行了shell(windows桌面)
shell再启动其他进程
- 一个命令启动一个进程,返回shell再启动其他进程
进程调度:
- FIFO
- Priority
多进程如何影响?
内存管理可以为多进程图像服务
多进程如何合作?
从纸上到实际:生产者——消费者实例
- 核心在于进程同步(合理的推进顺序)
多进程图像相关的所有知识:
2.3用户级线程
是否可以资源不动而切换指令序列?
- 进程 = 资源 + 指令执行序列
- 线程:将资源和指令执行分开;一个资源 + 多个指令执行序列;保留了并发的优点,避免了进程切换代价
多个执行序列 + 一个地址空间是否实用?
- 多线程的浏览器
create:
Yield:能完成切换——从一个栈到两个栈,PCB和栈相关联
用户级线程有局限性:
引出核心级线程:
内核级线程gcc -o explorer explorer.c …;
- ThreadCreate是系统调用
- Yield()用户不可见,调度点由系统决定
2.4内核级线程
充分利用多核的资源——内核级线程
核心级线程——两套栈
栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。
popa/popad
TCB简介
操作系统中一个线程对应着一个TCB(Thread Control Block),叫做线程控制模块,控制着线程的运行和调度。TCB组成
1、threadID:线程的唯一标识。
2、status:线程的运行状态
3、register:线程关于CPU中寄存器的情况
4、PC程序计数器:线程执行的下一条指令的地址
5、优先级:线程在操作系统调度的时候的优先级
6、线程的专属存储区:线程单独的存储区域
7、用户栈:线程执行的用户方法栈,用来保存线程当前执行的用户方法的信息
8、内核栈:线程执行的内核方法栈,用来保存线程当前执行的内核方法信息。
2.5内核级线程实现
内核级线程的五段论:
fork:创建进程的系统调用,会引起中断
一般寄存器:AX、BX、CX、DX
AX:累积暂存器,BX:基底暂存器,CX:计数暂存器,DX:资料暂存器EAX、ECX、EDX、EBX:為ax,bx,cx,dx的延伸,各為32位元
ESI、EDI、ESP、EBP:為si,di,sp,bp的延伸,32位元eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。如果用C语言来解释,可以把这些寄存器当作变量看待。
比方说:add eax,-2 ; //可以认为是给变量eax加上-2这样的一个值。
这些32位寄存器有多种用途,但每一个都有“专长”,有各自的特别之处。
EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。
EBX 是"基地址"(base)寄存器, 在内存寻址时存放基地址。
ECX 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。
EDX 则总是被用来放整数除法产生的余数。
中断返回(ret_from_sys_call)——iret——从内核态返回用户态
TSS:Task Segament Struct
eax == 0子进程;eax != 0父进程
GDT(全局描述符表)和 IDT(中断描述符表)是x86架构中用于存储描述符的表,它们在操作系统中发挥着关键的作用。
GDT(全局描述符表):
描述符: GDT 中的每个表项称为描述符,描述符包含了一些关于内存段(如代码段、数据段)的信息,比如基地址、段限制、访问权限等。段描述符: GDT 中的描述符用于定义不同内存段的属性,如代码段、数据段、堆、栈等。
全局性: GDT 是全局性的,即整个系统共用一个 GDT。每个描述符都有一个唯一的选择符,通过这个选择符,CPU 可以访问 GDT 中的相应描述符。
任务状态段(TSS): GDT 还包括任务状态段,用于定义任务的特权级别和状态。
IDT(中断描述符表):
描述符: IDT 中的每个表项也是描述符,描述符包含了中断门、陷阱门或任务门的信息。中断门和陷阱门: 中断门用于处理外部中断(如硬件中断),而陷阱门用于陷阱或异常处理(如软中断、系统调用、除零错误等)。
全局性: 与 GDT 类似,IDT 也是全局性的,整个系统共用一个 IDT。
中断处理: IDT 中的每个描述符指向一个中断处理例程(中断服务程序),当相应的中断或异常发生时,CPU 会跳转到相应的处理例程。
总的来说,GDT 和 IDT 在操作系统中的作用是管理和提供对不同类型的段和中断的访问和处理。这些表的结构和内容由操作系统内核进行管理和配置。在实模式和保护模式下,GDT 和 IDT 的设置和使用方式有所不同。在保护模式下,GDT 和 IDT 被广泛用于实现内存隔离和中断处理。
或异常处理(如软中断、系统调用、除零错误等)。
全局性: 与 GDT 类似,IDT 也是全局性的,整个系统共用一个 IDT。
中断处理: IDT 中的每个描述符指向一个中断处理例程(中断服务程序),当相应的中断或异常发生时,CPU 会跳转到相应的处理例程。
总的来说,GDT 和 IDT 在操作系统中的作用是管理和提供对不同类型的段和中断的访问和处理。这些表的结构和内容由操作系统内核进行管理和配置。在实模式和保护模式下,GDT 和 IDT 的设置和使用方式有所不同。在保护模式下,GDT 和 IDT 被广泛用于实现内存隔离和中断处理。