概述
-
执行程序:通过调度选中程序开始执行,在执行过程中,不断陷入操作系统提供各种服务支持,再调度选中程序,直到完成
-
功能: 有效(充分利用CPU、内存、磁盘等资源)
合理(公平的资源管理策略)
易用(用户界面和编程接口) -
作用:管理资源(硬件、软件)、 向用户提供服务(创建、执行、IO、统计)、对硬件机器扩展(屏蔽硬件细节、提供虚拟机器界面)
-
特征:并发(处理多个同时性活动)、共享(非同时互斥共享、同时共享有限系统资源)、虚拟(映射为若干逻辑实体)、异步(不可预知运行次序)
-
典型架构(用户态、内核态):Windows(硬件抽象、设备驱动、内核、图形窗口、执行体、内核态可调用接口、服务分发器、DLL)、Unix(硬件控制层、调度、进程间通信、存储管理、内存管理、文件系统、设备驱动、系统调用接口)、Linux(进程、调度、虚拟内存、物理内存管理、各种设备驱动、网络模块、陷入异常模块、中断处理模块、系统调用接口) 、Android(Linux内核、系统库和Android运行时系统、应用程序框架、应用程序)
-
分类:批处理(Spooling缓存I/O到磁盘)、分时(时间片、追求响应时间、交互式)、实时(严格时间、高可靠)、个人计算机(使用方便)、网络(通信、资源共享)、分布式(多机协同完成一项任务)、嵌入式(特定装置中的软硬件系统)
基本功能
- CPU管理, 作业调度
- 存储管理, 数据存取
- 设备管理, 与外围设备交互
- 接口管理, 向应用程序/用户提供交互接口
中断
系统在执行某个任务程序时收到中断信号, 需要让出当前CPU来执行中断处理。中断处理完成后,CPU再继续执行之前的任务程序。
- 软中断:
当前运行的程序产生的中断信号,通常是I/O请求;
不会直接中断CPU,需要内核去为当前进程完成一些类似I/O的请求;
中断过程: 进程->内核设备驱动程序。
- 硬中断:
由硬件产生,比如磁盘,网卡,时钟,键盘等;
直接中断CPU,通常一个中断只中断一个CPU;
中断过程: 硬件->CPU->内核设备驱动程序。
- 中断优先级:
硬件错误>时钟>磁盘>网络设备>其他终端设备>软件中断
动态链接和静态链接
动态链接: 在程序运行期间, 所依赖的模块来自于程序外部,在内存中动态加载/卸载,按需加载可节省内存;
静态链接: 在程序运行期间, 所依赖的模块来自于程序内部,即编译时已打包好,程序启动时便会载入内存。
进程与线程
进程的状态类型与转换
5个状态模型:
1)就绪(Ready)状态:指进程已处于准备好运行的状态,及进程已经分配到需要的系统资源,只要在获得CPU就可以执行
2)执行(Running)状态:指进程获得了CPU正在执行,在单处理机系统中,最多只有一个进程处于该状态
3)阻塞(Block)状态:指正在执行的进程,在执行过程中发生了某时间(如:I/O请求、申请缓冲区失败等)
为满足进程控制块对数据及操作的完整性要求以及增强管理的灵活性,通常在引入两种状态:创建状态和终止状态
4)创建状态:
创建一个进程要经过以下几步:
- 首先进程申请一个空白PCB,并向PCB中填写用于控制和管理进程的信息
- 然后为该进程分配运行时所必须的资源
- 最后把该进程转入就绪状态并插入就绪队列
引入创建状态是为了保证进程的调度必须是在创建工作完成之后
5)终止状态:
进程的终止状态有以下两步: - 首先,等待操作系统做善后处理
- 最后将其PCB清零,并将PCB空间返还给系统
当一个进程达到了自然结束点或是出现了无法克服的错误,或是被操作系统终结,则进入终止状态。进入终止状态的进程以后不能再执行,但在操作系统中保存状态码和一些计时统计数据供其他进程收集
进程与线程的区别
概念区别:
- 进程: 一个程序的动态执行过程, 分配资源的基本单位;
- 线程: 一个进程内调度的基本单位,一个进程包含一个或多个线程。
执行区别: - 进程:拥有独立内存空间,支持内部多个线程共享;
- 线程:必须依赖于进程来运行,每个线程有独立入口/执行序列/出口。
应用意义区别:
一个应用运行时对应一个或多个进程, 而线程在进程的基础上提供了可以执行不同调度逻辑的入口,易于实现任务的并发执行。
进程间通信的几种方式
- 管道pipe
管道是独立的文件系统,有自己的数据结构。实际上是只存在于内存中的文件,需要通过两个打开的文件句柄来进行操作,他们分别表示管道的两端。管道分为无名管道和有名管道。 - 共享内存
共享内存由一个进程创建, 能被其他进程访问, 最快的IPC方式。 - 消息队列
消息的链表, 存放于内核并由队列标识符标识;克服了缓冲区大小受限,信号信息有限,管道无格式字节流等缺点。 - 信号
用于通知某个进程某个事件已经发生,可触发进程已注册的处理函数。 - 信号量
一种计数器,用来控制多个进程对共享资源的访问, 通常作为一种锁机制, 常应用于进程间或进程内多个线程的同步。 - Socket
通过套接字通信,也可用于不同host之间的进程见通信。
进程同步,线程同步的几种方式
- 临界区(CriticalSection)(进程内线程同步)
一次只能被一个进程所占用的资源为临界资源;进程内访问临界资源的代码就是临界区。
进入区/临界区/退出区/剩余区 - 事件
基于事件机制, 一个进程/线程主动唤醒另一个进程/线程;比如监听通信端口A。 - 互斥量(Mutex)
类似临界区,但是能在进程间使用。Futex由一块能被多个进程共享的内存空间(对齐后的整型变量)组成, 保存在用户空间的共享内存中,通过原子操作进行操作。操作基本在用户空间内进行(需要仲裁时使用系统内核调用), 减少了系统调用次数, 提供系统性能。 - 信号量(Semphore)
信号量建立在原子操作上,使用信号量可以用来限制共享资源的线程数目。
其他相关知识点
- 线程的实现方式
用户级线程 | 内核级线程 |
---|---|
进程内的线程切换不用切换到内核进行, 内核并没有感知进程内的线程存在, 所以即使多线程并不能利用多核来进行操作。一个线程如果调用了阻塞系统调用, 那整个进程都会被阻塞。 | 也即内核管理的所有线程, 内核头既包含进程表, 也包含线程表。多线程可以利用到多核,多核下微观和宏观下都能做到并行。 |
混合模式: 内核线程可以在用户空间完成创建,应用的多个用户级线程可以被映射到内核线程中,提高并发效率。
-
用户态与内核态的区别
用户态:执行用户级别的代码,权限受限,由CPU标志flag来控制;
内核态:执行内核模块代码,比如执行磁盘IO,网络IO处理等。
应用进程可通过系统调用由用户态进入内核态,在缺页错误或中断发生时进入内核态。 -
用户栈与内核栈的区别
用户态:执行用户级别的代码,权限受限,由CPU标志flag来控制;
内核态:执行内核模块代码,比如执行磁盘IO,网络IO处理等。
应用进程可通过系统调用由用户态进入内核态,在缺页错误或中断发生时进入内核态。 -
内存池,进程池,线程池
所谓池的概念, 一般是指应用提前向内核批量申请资源,用于接下来的使用和回收再>利用, 减少资源的初始化和销毁次数等开销, 以达到提高系统性能的目标。
内存池:真正使用前申请一片内存区域,有新需求时取出其中一部分使用,不够用时再重新申请新内存。
进程池:应用预先创建一组子进程,所有子进程运行相同代码,拥有相同属性,比如PGID和优先级等;常见两种工作方式:
- 主进程通过随机或round robin算法来选择子进程作为新任务的服务进程;
- 通过一个共享队列来进行同步,所有子进程从该队列中获取任务,不过同时只能有一个子进程能成功获得新任务处理权。
线程池: 主要应用于任务小而多,处理时间短的场景,比如简单网页请求等。
-
进程调度算法
调度种类:
- 高级调度: 作业调度,决定把后备作业调入内存运行;
- 中级调度: 内存,外存交换区进行进程对换;
- 低级调度: 进程调度,决定把就绪状态的进程获得CPU。
CPU任务种类: 交互式任务和批处理任务。
调度算法:
- FIFO(FCFS): 公平简单,不利于交互式,不利于IO密集型作业;
- SJF:短作业优先调度,可以保证整体的最小等待时间,但不利于长作业;
- 优先权调度:拥有高优先权的作业优先处理, 有可能出现优先权低的任务“饥饿”情况;
- Round-Robin:按时间片进行轮转调度,让每个任务定时有响应但是上下文切换次数可能会过多。
- 多级优先级队列:按不同规则创建多个进程队列,不同队列拥有不同的优先级以及可以分配不同的时间片/调度策略。但是也存在”饥饿“可能性。
- 多级反馈队列:在多级优先级队列基础上,长期得不到运行的队列优先级会被提高。
内存管理
- 内存管理的技术发展
- 固定分区:系统初始化阶段,内存被固定划分成多个静态分区,进程可以一次性被装载到大于或等于自身空间的分区;
- 动态分区:动态创建分区,进程可以被装载到与自身相等大小的分区中;
- 虚拟内存分页:系统初始化阶段,内存被划分为多个大小一致的页框;每个进程被划分成多个与页框相等的页;根据实时需要加载一定数量的页。
- 虚拟内存分段:每个进程维护一个段表,系统维护一个空闲的块表,按需加载段。
- 段页式: 单按页加载的调度粒度太细,单按段加载的调度粒度太粗, 结合使用可有效提高系统性能。应用地址空间可划分成多个段,每个段又划分为多个固定大小的页,段偏移量在系统角度可看作是指定段中的一个页好和页偏移。
- 几种页面置换算法
- FIFIO: 淘汰最早调入的页面;
- OPT: 理想化的最佳置换算法,将标记为下次最迟才会被访问的页面淘汰;
- LRU: 将最近一段时间内最久没有被使用的页置换出去。
-
DMA定义及工作流程
DMA指外部设备不经过CPU而直接与内存交换数据的技术。
主要通过DMA控制器来实现: 控制器向CPU请求系统总线并获得控制权后, 与存储器直接进行数据交换, 完成后向CPU发送结束信号并交还控制权。 -
外存分配的几种方式
- 外存:CPU缓存及内存以外的存储器, 如硬盘/光盘等。
- 分配方式:
- 连续分配:创建文件时,分配一组连续的块, FAT中每个文件只需要一项,用以说明起始块及文件大小。
- 链式分配: 文件存放在若干不连续的物理块,各块之间通过指针连接。
- 索引分配: 每个文件在FAT中有一个一级索引, 包含文件各个分区的入口;这个索引信息保存在单独个一个块当中, 作为文件的访问入口。
- CPU中的缓存及OS中的缓存
CPU缓存 | 系统缓存 |
---|---|
介于CPU与内存之间的临时存储器, 有一级/二级/三级缓存之分 | 如块表,用于存放当前访问最频繁的少量活动页,提高数据存取速度。通过需要存取的数据所在逻辑地址,在块表中找到其对应的内存块地址, 结合其页偏移地址获得物理地址;如果块表中没有该逻辑页号,则通过查询空闲块来更新块空闲区信息;如果块表没有空闲区,则通过算法来淘汰块表中某一行,并填入新的空闲区。 |
死锁
- 死锁:每个进程无限等待被该组进程中另一进程占有的资源;与之对比,活锁 为先加锁再轮询不阻塞不推进,饥饿是由于资源分配策略如优先级导致得不到资源
- 死锁条件:互斥使用(资源独占),占有且等待(部分分配),不可抢占(不可剥夺),循环等待(进程等待环路)
- 资源分配图:进程是圆,资源类是方,资源实例是方框中黑点;申请边(进程,资源类)表示进程请求某类资源,分配边(资源实例,进程)表示资源分配给某进程
- 死锁定理:在资源分配图中,无环路必无死锁,有环路可能有死锁,有环且资源类只包含一个实例必有死锁
- 资源分配图简化:找只有分配边的资源,去掉边分配给需要的进程,自己变成孤点;重复上述步骤,若最后所有都是孤点则无死锁,否则有死锁
- 解决死锁:鸵鸟算法(不考虑死锁)、死锁预防(静态分配)、死锁避免(动态评估)、死锁检测和解除
- 死锁预防:破坏死锁必要条件;独占转为共享资源,一次性申请和分配、主动释放部分分配,操作系统帮助抢占,资源有序分配法(资源按热度编号,进程按资源号增序请求)
- 死锁避免:对进程发出的每一个能满足的资源申请进行动态检查,根据分配后系统是否为不安全状态(死锁)决定是否分配
- 安全序列:进程序列中任意进程,它还需要的资源不超过当前系统剩余资源与它之前的所有进程占有资源的和;此时系统为安全状态,一定无死锁,若不存在任何安全序列则为不安全状态,一定导致死锁
- 银行家算法:五类数组available, max[i], allocation[i], need[i], request[i];当进程i提出request[i]时,若不大于available则将allocation[i]加request[i]、available和need[i]减request[i],此时判断新状态是否安全,安全则分配否则等待
- 死锁检测:允许死锁发生,在资源不足、利用率下降时或周期性检测系统进展判断是否真的有死锁发生;死锁后解除死锁并以最小的代价恢复系统运行,可通过撤销死锁进程组、回退再启动、按某种原则逐一撤销进程或剥夺资源
- 哲学家就餐:同步互斥问题,五个哲学家日常行为是思考,两两间放一只筷子,饥饿时要从左右取两只筷子才可吃饭,都先拿右边筷子时出现死锁;解决方法包括最多允许四个哲学家、利用管程一次性拿两只筷子、设置哲学家的三种状态结合检测和PV操作、每个哲学家按筷子增序拿、由银行家算法将最后的筷子分配给已拿到一只的人