实际上, 我们编写的程序大多不是一个仅跟CPU和内存进行交互的程序, 我们还要用到文件系统, 文件, 硬件(硬盘, 打印机, 键盘), 这些资源时由操作系统来进行操控的, 因此我们要借助操作系统给我们提供的美丽接口来操控这些资源. 而操作系统是运行在内核态的. 我们自己编写的程序运行在用户态, 共同配合, 完成程序的功能
在离散式管理内存的方式中: 程序段的存储分为段式存储和页式存储, 逻辑地址和物理地址不同, 需要经过转换,
页式存储: 是将内存分成一个一个大小相等的页, 编写程序时使用逻辑地址, 要找到逻辑地址对应的物理地址, 就要先从驻留在内存的页表中找到逻辑地址的页号和页内偏移量, 得到其在内存块的物理地址.
优点是: 充分利用内存, 无碎片化管理, 但地址转换开销大
段式管理: 将主程序段, 函数段, 数据段, 放在大小不同的段中, 有的段只能读, 有的段可以执行, 这样管理能够更好地信息共享和保护, 由用户指定段号和段内偏移量, 在内存中不同的程序段占用一片连续的单位, 但整个进程是离散占用内存的. 跟页式存储管理一样, 依靠段表和段内偏移量来管理内存, 当然段表需要包括段的长度和段的保护码
段页式存储管理: 对每个段进行分页管理, 从而综合段式管理和页式管理的优点
当内存空间满, 就要按照页面置换算法换出一些页面到虚拟内存中, 换入需要运行的程序段
进程是分配资源的基本单位, 而资源的分配, 是在进程执行过程中, 操作系统分配的, 而线程只能使用进程分配的资源, 就算是线程申请了分配的资源, 得到资源的也是进程, 这个资源时相对该进程下的所有线程的, 因此资源时进程级别的. 协程其实这个概念的存在很没有必要, 协程就是在执行非CPU计算的耗时操作时, 切换到另一个程序段中去执行, 因此没有线程和进程切换的开销, 程序的执行速度更快.
中断: 又称为 外中断 操作系统内核态用于管理硬件, 文件系统, 系统资源, 进程切换.
而在用户态无法访问这些资源, 也无法进行进程切换, 要使用到硬件相关或者文件系统等系统资源
时, 程序就要切换到内核态运行, 实现这一 切换 的操作方式, 就是触发中断. 同时触发中断还能
让CPU可以和I/O并行处理, 提高效率.
异常; 又称为 内中断, 是指来自CPU的内部指令操控系统资源时发生错误(内存溢出, 操作溢出, 非法操作码), 异常需要马上被处理, 而中断有分级, 高级中断能优先执行并屏蔽低级中断
中断屏蔽: 高级中断执行的时候, 屏蔽响应低级中断. 而异常处理程序执行的时候, 可以不屏蔽, 或根据需要屏蔽外部中断.
系统调用: 操作系统操控硬件, 文件系统等系统资源, 而用户程序无法访问到这些资源, 因此需要借助某个 美丽接口 来访问这些资源. 而 系统调用 就是这个美丽的接口, 也就是操作系统向外部提供的api.
系统调用流程: 当执行到 系统调用API 时, 程序会保存用户态程序的执行信息, 使用trap指令陷入到内核态运行, 内核态执行完毕后, 才返回用户态运行, 并恢复现场, 程序在用户态继续执行
举个例子: 我想向一个文件中写入数据, 文件是系统资源, 操控时需要进入到内核态运行, 假设操作系统给我提供了一个 write() 的API接口, 执行到这一步时, 程序先会保护现场, 然后陷入到用户态, 将API需要的参数传递到约定的寄存器中, 比如说 文件描述符,写入的内容一般放在内存中, 然后操作系统打开文件, 将内容写入, 将文件关闭后, 返回到用户态执行, 用户态程序从API调用后的位置继续执行.
状态: 阻塞, 就绪, 执行
程序 = 代码+数据
进程 = 程序 + 运行
多进程 = 程序 + 多个运行 + 同时
多线程 = 部分程序 + 多个运行 + 同时
存储管理: 主要研究进程占用内存资源的调度
单道任务处理时内存空间的分配策略:
连续分配空间: 进程独占连续的一块内存空间, 适合于单进程情况下
交换: 将就绪的进程块从硬盘移到内存中, 时间片轮转法, 怎么交换的细节交给操作系统处理
覆盖: 固定一个常用的进程块放在内存, 其余多个固定区块用于调入将要执行的进程块, 用户自行组
织覆盖哪一段
多道任务处理内存空间的分配策略
多道连续内存空间分配策略: 不同的进程占用一片连续的空间
多道离散内存空间分配策略: 分页, 分段
资源互斥: 同一时刻只能有一个进程进入临界区
占有等待: 资源占用后, 如果任务为完成, 就占有资源并等待
不可剥夺: 资源占有后, 任何其他进程不能剥夺我占有资源的权利
循环依赖: 进程A和进程B互相依赖对方手中的资源