计算机操作系统--哈工大
![](https://i-blog.csdnimg.cn/blog_migrate/247d6f8d9828dd5cb94dc05028a19ae8.png)
![](https://i-blog.csdnimg.cn/blog_migrate/769e35988126d1b48342762f641a56f5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78c16f5e395e2c68acaea0781d7b4447.png)
打开计算机发生了什么?
![](https://i-blog.csdnimg.cn/blog_migrate/f766392f0dbe37548087a3cbbb2a18c9.png)
一个扇区是512字节
0磁道0扇区是操作系统的引导扇区
![](https://i-blog.csdnimg.cn/blog_migrate/ffbaa95e2f682ec99f5fc12945854624.png)
取指执行
接口:连接两个东西,信号转换,屏蔽细节
系统调用的实践
![](https://i-blog.csdnimg.cn/blog_migrate/cd04c309004bb233d6b0645efb527f3b.png)
DPL是用来描述目标内存段的特权值
CPL 当前的特权级
![](https://i-blog.csdnimg.cn/blog_migrate/ca6b43294a0886c642af53c88a582efc.png)
CPU进程
![](https://i-blog.csdnimg.cn/blog_migrate/8067d04f9146eb8acd9ec9e09632baad.png)
![](https://i-blog.csdnimg.cn/blog_migrate/13e9ec0d0bfe6c64e7940e69a72f7d0f.png)
交替的三个部分:队列操作+调度+切换
多进程图像
![](https://i-blog.csdnimg.cn/blog_migrate/1881107922d570f5bea3959cc9fcfd14.png)
进程一对地址100的写入会影响进程二的代码
解决办法:通过虚拟内存分离进程,分离地址。
进程管理连带内存管理形成多进程图像
![](https://i-blog.csdnimg.cn/blog_migrate/233ca8acc4f82dfaeb65eb8dcf313a46.png)
给代码段上锁,以达成合理的进程推进顺序
![](https://i-blog.csdnimg.cn/blog_migrate/88a389c1a1ab0513728ba80b7d0681e9.png)
在可能的执行序列里会造成错误,两个进程不可以随意的切换
学习目标
![](https://i-blog.csdnimg.cn/blog_migrate/69a1028c2d7cd0bd51adbfdb5260ecde.png)
用户级线程
线程切换
![](https://i-blog.csdnimg.cn/blog_migrate/7eb22c1f4b0a3233988a7c49d9fed6f2.png)
比进程切换更快捷,不换资源
实质上是映射表不变而PC指针变
同时出发,交替执行
![](https://i-blog.csdnimg.cn/blog_migrate/ebf6f8f91cd8cb1d548d3f6a6aaecb0c.png)
切换核心yield
yield是用户程序
会出问题的:
第一个线程里的yield执行后跳到第二个yield,204压栈,之后第二线程里的yield执行跳到第一个线程(不弹出栈),第一个执行完后见到‘}’,这个会编译成为一个ret,此时栈弹出一个地址 404,跳回到第二个线程
![](https://i-blog.csdnimg.cn/blog_migrate/401e2f62cd936a013c620dd8dbd8c117.png)
正确的:
应该去掉yield函数中的jmp,jmp跳出之后不会ret即不会弹出栈,从第二个线程跳回来之后204会执行两遍
用yield的右括号来实现弹栈
栈分离,每个线程用自己的栈,yield时先保存栈
![](https://i-blog.csdnimg.cn/blog_migrate/1271c517bdc019e990fa320c71c70d3a.png)
可能的问题
用户级线程会出现的问题
进程阻塞后内核会进入别的进程,因为看不到线程。此时这个函数就是呈现一种卡住了的样子
此时虽然启动了多个线程,但是并没有用
![](https://i-blog.csdnimg.cn/blog_migrate/c206c7d6675c4d1b98c573939164515a.png)
核心级线程
![](https://i-blog.csdnimg.cn/blog_migrate/7b88e28f7707460b19e91ffe5f51e474.png)
核心级线程发生阻塞就可以有效地运行别的线程
ThreadCreate
![](https://i-blog.csdnimg.cn/blog_migrate/82bd9f4549d00696a30b55a7241dd6b7.png)
内核级线程
多进程和用户级线程都无法在多核上起效果,因为多进程需要切换资源,而多核CPU只有一套MMU和Cache。用户级线程由于无法做系统调用到底层给OS分配硬件。
![](https://i-blog.csdnimg.cn/blog_migrate/38f7aa716f86355fea36cd1bc0b046ad.png)
内核栈
![](https://i-blog.csdnimg.cn/blog_migrate/2ac9a9fadd7596d715fcf89a2ffc3ac5.png)
切换线程的时候根据TCB切换一套栈
引起中断就会进入内核栈
进入内核栈时会首先将用户栈的SS SP EFLAGS IP CS入栈
IRET指令包含ret功能,还会将SS SP等弹出栈
![](https://i-blog.csdnimg.cn/blog_migrate/39e604c494d0eac4c57bbcc00c51622a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7d612cbb47b45809faae61709b11537b.png)
开始内核中的切换 switch_to
![](https://i-blog.csdnimg.cn/blog_migrate/915af358e431acf60d6ef3ecad7be600.png)
用户栈进入内核栈,利用TCB找到切换目标内核栈,再根据内核栈IRET找到用户栈,运行结束后利用RET返回(思路和用户栈切换很像)
![](https://i-blog.csdnimg.cn/blog_migrate/a9f2734f392aae75ed7d476f3adac95d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/61491c252e1045a2ea2c47b692e24e3f.png)
ThreadCreate
![](https://i-blog.csdnimg.cn/blog_migrate/6b8ea04753ed96d1740abc800863f69c.png)
TCB tcb = get_free_page()开辟一段内存
*krlstack = 初始化内核栈
*userstack = 传入用户栈
用户级线程,核心级线程的对比
![](https://i-blog.csdnimg.cn/blog_migrate/25e6a12af650fe02888413a86a4cffc7.png)
核心级线程实现实例(未学会 )
听不懂,还得看从实模式到保护模式,累了
等过一段时间回来把哈工大 核心级线程实现示例重新看一遍