1. 计算机存储
CPU 缓存 内存 磁盘
2.进程 和 线程
单进程,读,解压,播放,效率低;分成三个进程,又要保持独立,又要通信实现信息共享,系统开销大,创建进程、结束、切换 两个进程通信,通过系统调用,通过内核绕一圈 线程分为用户线程和内核线程 用户线程:内核不感知线程的存在,其管理由用户空间完成,创建销毁切换通过调用库函数实现, 内核线程:内核管理用户空间的线程,内核会维护线程切换的上下文信息,通过TCB块感知线程并进行控制,一个进程的PCB有指针指向它相应的线程的TCB 用户空间 运行的代码,应用程序 内核空间 (系统调用)管理,设备管理,文件管理,内存管理,进程线程管理
用户空间的进程 和 内核空间怎么打交道? 比如hello word代码运行在用户空间,当需要打开一个文件,就用系统调用,即应用程序不能直接申请系统资源,需要通过系统调用的方式向操作系统提出请求,
进程切换 由于分配的时间片用完、或者需要终端进行IO操作、或者被抢占,将A进程状态的信息PCB块保存到内核,另一个B进程从内核之前保存的状态进行恢复,被中断再次保存,A可以恢复,从内核恢复状态 进程创建 fork()将进程进行复制,代码数据堆栈同,PID不同 exec() 重写当前进程
int pid = fork()
if(pid == 0){子进程程序,exec()}
else{父进程程序}
一个进程,一个pid ,内核维护一个PCB块,fork后生成新的pid进程
fork()循环三次,会由一个进程复制出7个进程 fork开销大,需要复制父进程的内容到子进程,采用vfork创建时不复制,使用时直接加载exec
3.处理机调度
处理机调度功能: 选进程,选CPU 1.挑选下一个要执行的进程,从就绪队列里挑选下一个占用CPU运行的进程 2.从多个CPU中挑选就绪进程可用的CPU资源
调度程序:内核函数,挑选就绪进程 调度策略:选择进线程原则 调度时机:什么时候进行调度,被抢占或主动放弃CPU使用
调度算法: 先来先服务:就绪队列排队 短进程优先:作业时间长短,按照预期作业时间排序,若有更短时间进程,比较当前进程剩余时间,考虑是否抢占;可能会导致饥饿,预估时间问用户,或者用历史预估未来 最高响应比优先:就绪队列在队列里的等待时间,避免饥饿,根据等待时间+预估执行时间/预估执行时间,值越大先进行 时间片轮转算法:在先来先服务基础上添加最长服务时间限制,
4.同步和通信
临界区:进程中访问临界资源的一段需要互斥执行的代码(那段在任何时刻只允许一个进程执行的代码)
一段代码分为:进入,临界,退出,剩余区
锁:抽象数据结构,由上锁解锁两个变量+请求锁+释放锁
同步:协调多线程对共享数据的访问,任意时刻只能有一个线程执行临界区代码
信号量:抽象数据结构,由一个整型变量s(共享资源数目)+两个原子操作 P申请,s-1,s<0,等待,否则继续 V释放,s+1,s<=0,说明唤醒了另一个等待的进程 因为两个原子操作是操作系统完成的,优先级要比进程高,不会被打破 传说中的生产者和消费者问题 多个生产者往里写,一个消费者消费怎么实现,采用信号量 问题分析: 缓冲区是临界区,任意时刻只能有一个线程操作 缓冲区空时,消费者等待 缓冲区满时,生产者等待 资源信号fullBuffers 有数据才能往外读 资源信号emptyBuffers 空了才能往里写 条件变量 管程内的等待机制,管程和临界区类似,但管城可以有0或多个条件变量,一个条件变量表示一个等待原因
哲学家就餐问题
死锁
死锁背景分析: .资源:CPU执行时间、内存空间、I/O设备,每类资源有N个实例 进程:申请资源、占用资源、释放资源 可重用资源:处理器、IO通道、寄存器、设备、文件、数据库、信号量
死锁处理
死锁预防:限制并发进程对资源的请求,让其不满足死锁条件 打破互斥:对公共资源设置缓冲队列 打破持有并等待:一次申请够所有资源再执行 打破非抢占:一旦申请不到资源,也放弃原有的 打破循环等待:资源排序,进程按序请求 死锁避免:分配资源时判断是否会造成死锁,会则不分;首先,进程声明最大需求资源数,可满足则分配,其次,动态检测资源分配状态是否安全,确保不会出现环形等待,安全状态:已占有进程存在安全序列,序列中,每个进程需要的资源 < 当前可用+当前进行序列之前所有进程所占资源,即有进程释放资源,我可用等到
银行家算法: 客户申请最大贷款,银行有就贷给它
死锁检测: 死锁终止:进程终止或者抢占资源,终止进程,一次终止一个直到死锁消除,进程终止顺序可用按照进程优先级;抢占资源,选择低成本进程抢占资源,有可能会造成饥饿
进程通信
间接通信
操作系统维护消息队列实现进程间的收发信息,每一个消息队列有唯一标识,进程需要知道消息队列名字
直接通信
进程需要知道对方名字
阻塞(同步)和非阻塞(异步)通信
阻塞发送:发送者发送消息后进入等待,知道接收者成功收到 阻塞接收:接收者发出请求信号后进入等待,直到接到信息 非阻塞通信:发送者发出消息后不管有没有被接,可立即进行其他操作
信号和管道:
信号:快速的响应机制,传送量小,只有一个信号类型;比如CTR +c信号 实现:进程注册信号处理函数,内核发现其他进程或设备发出相应信号后,内核把信号送给指定进程
管道:进程间基于文件的通信 子从父继承文件描述符,只关心管道是谁,不关心管道那边是谁 读管道:read(fd, buffer,nbytes) scanf() 的实现就是如此 写管道:write(fd,buffer,nbytes) printf() 创建管道: pipe(rgfd),rgfd是两个文件描述符数组,一个读,一个写fd
ls | more 中间的就是管道, | shell给两个命令建立一个管道 问题:shell是什么?
消息队列
操作系统维护的,单位为字节序列,间接通信,消息队列独立于进程,可用实现不同生命周期的进程通信
共享内存
多个进程可以同时共享一块内存,快速,不需要系统调用没有用户和内核之间的切换,但需要同步机制协调访问冲突 共享内存通过页表映射到同一块物理内存
|