操作系统一直学的不太好,俗话说“缺什么补什么”,慢慢补上吧!!
秋招加油!!会持续更新,everyday!
认识操作系统
在硬件的基础上,计算机安装了一层软件,可以通过这层软件响应用户指令从而控制硬件,则这层软件称之为**“操作系统”**。
图形用户界面(Graphical User Interface, GUI)指的是带有图形界面的操作系统。
基于文本,命令行的称为Shell。
计算机两种运行模式:内核态 + 用户态。
内核态也称: 管态 + 核心态。
Shell 或GUI 处于用户态,允许用户运行其他程序。如web浏览器等。
计算机硬件
CPU\内存、I/O设备都与总线串联,通过总线与其他设备通信。
CPU主要和内存进行交互,从内存中提取指令并执行。
CPU内部包含寄存器来保存关键变量和临时结果。
程序计数器会指示下一条需要从内存提取指令的地址。
堆栈指针:指向内存中当前栈的顶端,包含输入过程中的有关参数、局部变量以及没有保存在寄存器中的临时变量。
PSW:程序状态字寄存器,跟踪当前系统状态。在调和I/O中,有重要作用。
时间多复用的CPU中,操作系统往往会停止运行一个程序而运行另一个。所以,每次当操作系统停止运行一个程序时,操作系统会保存所有寄存器的值。
现在CPU能够有单独访问、解码、执行单元。流水线如下所示:
超表量CPU:
多线程和多核芯片
多线程允许CPU保持两个不同的线程状态,并在纳秒级的时间完成切换。但是并不提供真正的并行处理,在一个时刻只有一个进程在运行。
线程是一种轻量级进程。每个线程对操作系统来说都像是一个CPU。
多核芯片如下:
GPU:有成千上万个微核组成的处理器。
内存
寄存器和CPU一样快。
高速缓存,由硬件控制。(RAM,随机存储器。 可读可写,机器关闭,则数据丢失。)
时钟周期的解释:
主存:RAM(易失性)\ROM、PROM和闪存。
磁盘:机械装置。有磁道。
i/o设备
操作系统概念
进程
进程本质上是操作系统执行的一个程序。(可以看做是容纳运行一个程序所有信息的容器)。
与每个进程相关的是地址空间。从最小存储位置到某个最大值的存储位置的列表。 在这个地址空间中,进程可以进行读写操作。
进程间的通信:
地址空间
用主存来保护一些正在执行的程序。 虚拟内存技术:把部分地址空间装入主存,部分留在磁盘上。需要时来回交换。
文件
创建文件、删除文件、读文件、写文件都需要系统调用。
目录:可以把文件分组。 目录之间嵌套,产生文件系统。
管道
管道是虚文件,可以链接两个进程。
保护
rwx位:
r表示可读,可以读出文件的内容 --数字4表示
w表示可写,可以修改文件的内容 --数字2表示
x表示可执行,可运行这个程序 --数字1表示
没有权限的位置用-表示
Shell
系统调用
2021.6.30
进程和线程
进程是对正在运行中的程序的一个抽象。
即使可以使用的CPU只有一个,他们也支持(伪)并发操作。会将一个单独CPU抽象为多个虚拟机的CPU。
原因:CPU智能运行一个进程,但是会在每个进程之间不停地切换,所以会产生并行的感觉,即:(伪)并行。
进程模型
每个进程都有各自的伪CPU,CPU也会在各个进程之间来回切换。
进程是某一类特定活动的总和。他有程序、输入输出以及状态。
进程的创建
- 系统初始化(init)
ps 程序可以列出正在运行的进程
-
正在运行的程序执行了创建进程的调研(fork)
-
用户请求创建一个新进程
交互式用户请求,双击某个软件。 -
初始化一个批处理工作
主要命令如下:
父子进程各有不同的地址空间。
进程的终止
- 正常退出
exit linux
ExitProcess windows
- 错误退出
cc foo.cc
-
严重错误
直接终止进程。 -
被其他进程杀死
kill linux
TerminateProcess windows
进程体系
UNIX:整个操作系统中所有的进程都隶属于一个单个以init为根的进程树。
在UNIX中,进程不能剥夺其子进程的进程权。
进程状态
每个进程是一个独立的实体,但是一个进程的结果可以作为另一个进程的输入。
cat chapter1 chapter2 chapter3 | grep tree
第一个进程是 cat,将三个文件级联并输出。
第二个进程是 grep,从输入中选择具有包含关键字 tree的内容。
- **运行态:**进程实际占用CPU时间片运行时
- **就绪态:**可运行,但是其他进程正在运行
- **阻塞态:**除非某种外部事件发生,否则他不能运行。
进程的实现
线程
为什么需要线程?
- 多线程之间会共享同一块地址空间和所有可用数据能力。
- 线程比进程更轻量级,更容易创建,也更容易撤销,创建一个线程要比进程快10-100倍
- 多线程是CPU密集型,虽然不能性能上增强,但是若存在大量计算和I/O处理,则多线程会彼此重叠进行,从而加快应用程序执行速度。
多线程解决方案
web服务器可以把获得大量访问的页面集合保存在内存中,避免到磁盘中调用这些页面,从而改善性能。
单线程解决方案
在下一个请求到达之前完成工作。
状态机解决方案
有限状态机:有限状态机,(英语:Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
常见的计算机就是使用有限状态机作为计算模型的:对于内存的不同状态,CPU通过读取内存值进行计算,更新内存中的状态。CPU还通过消息总线接受外部输入设备(如键盘、鼠标)的指令,计算后更改内存中的状态,计算结果输出到外部显示设备(如显示器),以及持久化存储在硬盘。
电脑游戏设计中也经常使用有限状态机模型。以水果忍者游戏为例,游戏中水果的状态是有限状态,其运行轨迹是由模拟物理运动规律的计算公式运算而成的,一个香蕉抛起来后会按照抛物线运行,其每一帧位置变化都是一个状态的改变,状态改变通过计算公式来决定。当然作为游戏不会仅仅这么简单,如果这么简单就是动画了,游戏还有复杂的人机交互事件,比如用手在屏幕上“切”了水果,水果感知到这个事件后,会按照程序逻辑进入爆炸状态。
见:
https://blog.csdn.net/baixiaoshi/article/details/77493899
三种方案的对比
经典的线性模型
上图:每个进程都有自己的地址空间和单个控制线程。每个线程都在不同的地址空间中运行。
上图:一个进程三个线程;每个线程都在相同的地址空间中运行。
线程没有强独立性;可以有一样的地址空间,即可以拥有同样的全局变量。
线程调用 | 描述 |
---|---|
pthread_create | 创建线程 |
pthread_exit | 中止线程 |
pthread_join | 线程调用,用来等待特定线程的终止。 |
pthread_yield | 释放CPU来运行另一个线程的属性结构 |
线程实现
- 在用户空间中实现线程;
优势:
效率高、不需要上下文切换、不需要对内存高速缓存刷新,线程调度便捷。
劣势:
要避免阻塞调用,否则会发生缺页故障。 - 在内核空间中实现线程;
优势:
内核维护了一张进程表来跟踪系统状态。
劣势:
在内核中创建或销毁进程开销比较大。
- 在用户和内核空间中混合实现线程。
进程间的通信(Inter Process Communication,IPC)
主要是三个问题
- 一个进程如何传递消息给其他进程?
由于共享一个地址空间,所以具有相同的运行环境,可以通过高级语言编写多线程代码解决。 - 如何确保两个或多个线程之间不会互相干扰,如:抢购最后一个座位。
- 数据的先后顺序。A产生数据,B打印数据,那么B要等待A完成后才能进行打印。
竞态条件
定义:俩个或多个线程同时对一共享数据进行修改,从而影响程序运行的正确性,这种就被称为 竞态条件。
临界区
如何对竞态条件避免?
禁止一个或多个进程在同一时刻对共享资源(共享内存、共享文件)进行读写。
需要设定互斥条件。除该进程之外的其他进程禁止访问共享资源。
我们把对共享内存进行访问的程序片称为 临界区。使俩个不同进程不可能处于临界区,即可避免竞争条件。
忙等互斥
屏蔽中断
在单处理器系统上,最简单的解决方案是,让每个进程在进入临界区后 立即 屏蔽所有中断,并在离开临界区之前重新启用。
锁变量
单个共享的(锁)变量,初始值为0。
当一个线程想要进入关键区域时,先看锁的值是否为0,如果是0,进程将其设置为1,之后再进入关键区域,若锁的值为1,那么进程将会一直等待锁变量变为0.
严格轮询法
该方法违反了:位于临界区外的进程不得阻塞其他进程,进程0被一个临界区外的进程阻塞,所以不太行。
Peterson解法
#define FALSE 0
#define TRUE 1
/*进程数量*/
#define N 2
/* 现在轮到谁 */
int turn;
/* 所有值都初始化为 0 (FALSE) */
int interested[N];
/* 进程时 0 或 1 */
void enter_region(int process){
/* 另一个进程号 */
int other;
/* 另一个进程 */
other = 1 - process;
/* 表示愿意进入临界区 */
interested[process] = TRUE;
turn = process;
/*空循环*/
while(turn == process
&& interested[other] == true){}
}
void leave_region(int process){
/* 离开临界区 */
interested[process] == FALSE;
}
TSL、XCHG指令
TSL RX,LOCK
测试并加锁。
睡眠与唤醒–生产者-消费者问题
Peterson、TSL、 XCHG都有忙等待的缺点。浪费了CPU的时间。
所以采用 sleep 和wakeup .
sleep:造成调用阻塞。
wakeup:唤醒线程。
生产者-消费者问题 也称 有界缓冲区问题
生产者:将信息放入缓存区。
消费者:将信息从缓存区取出。
M个生产者和N个消费者问题。 需要监听变量,用来监视缓冲区数据。
/* 缓冲区slot槽的数量 */
#define N 100
/* 缓冲区数据的数量*/
int count = 0
// 生产者
void producer(void){
int item;
/* 无限循环 */
while(TRUE){
/* 生成下一项数据 */
item = produce_item()
/* 如果缓存区是满的,就会阻塞 */
if(count == N){
sleep();
}
/* 把当前数据放缓冲区中 */
insert_item(item);
/* ी增加缓冲区数量*/
count = count + 1;
if(count == 1){
/*判断是否为空*/
wakeup(consumer);
}
}
}
// 消费者
void consumer(void){
int item;
/* 无限循环*/
while(TRUE){
/* 如果缓存区是空的就会阻塞*/
if(count == 0){
sleep();
}
/* 从缓存区中取数据 */
item = remove_item();
/* 减少缓存区监听到的数量 */
count = count - 1
/* 判断是否是满的 */
if(count == N - 1){
wakeup(producer);
}
/* 答应数据项*/
consumer_item(item);
}
}
会产生唤醒丢失问题,需要增加 唤醒等待位
信号量
解决唤醒丢失问题。
互斥量
管程
调度
调度算法分类
- 批处理
- 交互式
- 实时
调度算法的目标:
批处理系统:
批处理系统中的调度
先来先服务
短作业优先
在所有进程都可以运行的情况下才能使用短作业优先 。
交互式系统中中的调度
轮询调度
开销特别大!!
优先级调度
每个进程都被赋予了一个优先级,优先级高的进程先运行。