操作系统 -> 1
好久之前看的b站课 有点搞不下去 不过还是要坚持 ... 图片后续传一下
操作系统的定义
是计算机硬件和应用之间的一层软件
是管理硬件的软件系统
- 方便我们使用硬件、如何使用显存
- 高效的使用硬件,如开多个终端
操作系统管理的硬件
- CPU管理
- 内存管理
- 终端管理
- 磁盘管理
- 文件管理
- 网络管理
- 电源管理
- 多核管理
学习操作系统的层次
- 从应用软件出发"探到操作系统"
- 集中在使用计算机的接口上
- 使用显示器、CPU、文件
- 从应用软件出发"进入操作系统"
- 一段文字是如何写到磁盘上的
- 从硬件出发"设计并实现操作系统"
- 给你一个板子,配一个操作系统
计算机怎么工作的
- 从白纸到图灵机
- 就是一个计算模型
- 同图灵机到通用图灵机
- 设置控制器动作就是设置处理数据的逻辑 ---> 程序
- 把程序载进来 解释执行这个程序 出相应的结果 ---> 冯诺依曼存储程序思想
- 把程序载入到存储器(内存)里,用一个PC(IP指令)指针指向当前处理的指令,把指令载入进来,就完成了控制逻辑。然后控制器解释执行。
- 取指执行
打开电源,计算机执行的第一句指令是什么
PC=?
PC: 存放当前欲执行指令的地址
操作系统启动
jmpi 0,8
0->ip 8->cs
16位和32位区别的本质是什么?
- CPU中的解释程序不一样
怎么切换到另外一条指令
cr0
一个非常酷的寄存器
- 如果寄存器的最后一位是0 — 16位模式(实模式)
- 如果寄存器的最后一位是1 — 32位模式(保护模式)
- 导致CPU要走另外一条解释执行的电路
gdt
Global describe table 全局描述符表
保护模式下的地址翻译和中断处理
是由硬件结构帮做的 目的
: 快
(x86)
- 在16位的时候 cs放的就是地址 左移四位也是地址
- 但是在32位的时候 cs放的就是
选择子
selector
查表的下标 并且偏移8位 - 真正的基址是放在表项中 所以是选择子 从表中取得基址的项(表中必须有内容) 再和ip偏移产生32位的地址
- gdt t-> table
- 为了表中必须有内容 所以setup做了一件事
system模块
System模块(目标代码)中的第一部分是什么呢?(0地址处)
如果想要整个系统好使
-
必须第一段是bootsect
-
因为bios只会从0磁到0扇区开始读 如果不是则整个系统就乱套了
-
第二段是setup
- bootsect是直接从第二个扇区往后读 想读出来的是setup 所以操作系统第二个部分必须是setup
-
第三段是system
- bootsect把后面的内容读进来(第三段开始) setup跳到后面的第一个部分
- 这一系列才会顺利有序的执行 只要中途一点出错 就会死机
-
以上称为
image
操作系统的镜像- 有一堆源码 源码通过
Makefile
产生了一个操作系统的镜像(必须要长成上面的样子) - 可以将image放到0磁到0扇区 这个是可以通过指令和工具控制的 (并且可以写到磁盘的任意位置)
- 在利用image进行开机引导的时候 就会出现上面的样子
- 操作系统顺理成章的被读了进来、被立了起来,被初始化 然后会产生一个桌面 shell
head.s
是system模块中的第一个文件(汇编文件)- 有一次初始化了
idt、gdt
表
- 有一次初始化了
- 下面是
main.c
c函数文件永远不会返回的函数
一旦返回 则死机- 一系列初始化的操作
mem_init
- 执行内存的初始化
Makefile
是一种树状结构 - 有一堆源码 源码通过
操作系统接口
接口 Interface
连接两个东西、信号转换、屏蔽细节
用户如何执行计算机
1.命令行
- 命令程序
2.图形按钮
- 消息框架程序+消息处理程序 (循环调用消息处理函数)
3.应用程序
实际上都是程序
上层应用通过一些c语言加上一些关键的、重要的函数来使用底层硬件。
而这些重要的、关键的函数就是接口。
接口表现为函数调用,又由系统调用,所以称为系统调用。
系统调用
POSIX : Portable Opreating System Interface of Unix (统一接口)
- 任务管理
- fork 创建一个进程
- execl 运行一个可执行程序
- pthread_create 创建一个线程
- 文件系统
- open 打开一个文件或目录
- EACCES 返回值 表示没有权限
- mode_t st_mode 文件头结构 文件属性
系统调用的实现
什么是系统调用?
由操作系统提供的函数调用 是操作系统给上层应用提供的接口
上层应用程序通过调用这些函数来进入操作系统 使用操作系统的功能
类似插座 插上就可以使用 但是插座后面的电路是怎么连接的 这就需要好好去学习
系统调用的直观实现
问题:操作系统也在内存中 应用程序也在内存中 应用程序想访问操作系统提供的功能 为什么不能直接跳进去(move)访问
不能随意的调用数据 不能随意的jmp
可以看到root密码 可以修改它 没有安全性
可以通过显存、缓冲区看到别人word里的内容
内核(用户)态、内核(用户)段
将内核程序和用户程序隔离
- 区分内核态和用户态:一种处理器"硬件设计"
计算机对内存的使用都是一段一段的使用
内核段的内存执行在内核态下 用户态的程序不能跳过内核段
内核态可以访问任何数据,用户态不能访问内核数据。
两个段寄存器:DPL ≥ CPL
DPL :描述目标内存段 (内核段)
- (destination/describe Privilege Level) 目标特权级
- 0是内核态 3是用户态 1 2是OS服务
- 特权级:数字越大越低
- 所以在每次访问的时候都要看看所访问的(move)特权级和当前的特权级比较如何
- 所以按照表达式 CPL的数字应该小一些 对应的特权级就应该更大
- 如果CPL = 3 则只能访问DPL = 3的 如果DPL = 0 则不能访问
- 这条指令由硬件检查 是否合法 是否满足特权级要求 如果不符合 则进不去
CPL:
- current privilege Level 当前特权级
硬件也提供了"主动进入内核的方法"
终断指令int
- int指令将使cs中的CPL改成0 "进入内核"
- 这是用户程序发起的调用内核代码的唯一方式
系统调用的核心
- 用户程序中包含一段包含int指令的代码
- 代码就是c语言的库函数
- 表面上看只有一个open函数 但背后发生了很多工作
- 不是所有的中断都能进入内核 只有设计的中断才能进入内核
- 代码就是c语言的库函数
- 操作系统写中断处理 获取想调用程序的编号
- 例如 根据open函数中的中断指令 来跳去相应地方执行
- 操作系统根据编号执行相应代码
只有唯一的一个中断 int 0x80 指令 可以进入
操作系统的历史
批处理操作系统:
Batch system
如果有很多计算任务需要计算机来完成
计算机首先完成第一个任务,不管完成还是出错,到了中途是不会停下来的。
马上就开始执行第二个任务。是一直执行下去的。
实际上就是一个监控程序。只要发现了第一个任务出错或者完成,马上修改PC指针执行第二个任务。以此类推。(会把出错的任务错误信息写到磁带上,分析,分析之后再写一个任务放到后面,批处理再进行执行。)
多道程序
multiprogramming
如果一台计算机要干很多事,那么仍然采用批处理操作系统就不合适了。
因为一旦开始处理第一个任务,那么就必须等待第一个任务执行完才可以进行下一个任务。如果跳到第二个任务就没有办法再回到第一个任务。所以第二个任务就要一直等着。
如果第一个任务是一个IO任务,有写磁带的操作,那么写磁带的执行是非常慢的。中途时间非常长。
等待时间过长,对于一个计算机来说,是非常不合适的。
所以相对于等待,来回切换执行程序就更好一些。所以就出现了一种结构:
多道程序处理结构。
多个任务同时出现在计算机中 多道程序同时执行、交替执行、向前推进
这样就出现了作业之间的交替、切换、调度。
多进程结构和进程管理概念萌芽
分时系统
timesharing
计算机进入多个行业,使用人数增加,每个人都要启动一个任务,那么如果按照批处理的话,如果第一个任务一直没有出错一直运行,那么第二个人就等太久了。
所以出现了分时系统:
第一个任务执行一会,就切出去给第二个任务再执行一会,以此类推。再反过来执行第一个。
这样每个人的任务就一段一段向前推进。
这个系统本质上和多任务处理没有什么区别。
唯一的区别就是多任务是启动IO CPU没法执行的时候才切换。
分时系统是定时的切换
Unix
Ken Thompson 、 Dennis Ritchi
Linux
Linus Torvalds
DOS
CP/M -> QDOS -> MS DOS -> Windows -> Unix -> Syetem -> Mac OS -> ios
核心思想仍然是程序执行、多进程、程序执行带动其他设备执行使用的基本结构
但是用户使用的感觉倍加重视了:各种文件、编程环境、图形界面
CPU管理
操作系统的核心就是管理计算机硬件:
CPU、内存...
CPU是计算机内最核心的硬件
在管理CPU的时候引出了多进程图像