操作系统导论&深入理解计算机系统

《Operating Systems Three Easy Pieces》

第1、2章(p1-15)

操作系统的重要组成部分:虚拟化(virtualization)(CPU和内存)、并发(concurrency)、持久性(persistence)
设计目标:
①建立抽象使系统方便和易于使用
②提供高性能,最小化系统开销
③在应用程序之间、OS和应用程序之间提供保护③构建可靠、能长时间不间断运行的系统
简单历史:最早期的一些库→超越库的系统调用、有用户权限之别→多程序时代引入并发→个人计算机时代的小型操作系统

第3-11章(p18-81)

虚拟化要做的是将CPU虚拟成多个虚拟CPU并分给每一个进程使用
每一个应用都以伪自己在独占CPU,但实际上只有一个CPU
时分共享CPU:让一个进程只运行一个时间片,然后切换到其他进程
开销overhead是性能损失
进程API:创建create, 销毁destroy, 等待wait, 其他控制miscellaneous control, 状态status.

  • 操作系统运行程序前,必须将代码和所有静态数据如初始化变量,加载load到内存中,加载到进程的地址空间中。(就是os从磁盘读字节,然后放到内存某处
  • 然后为程序的运行时栈(放局部变量、函数参数、返回地址)分配一些内存
    进程状态:运行running, 就绪ready, 阻塞blocked, 初始initial, 最终final
    调度scheduled: 就绪→运行
    取消调度deschuduled: 运行→就绪

【记得做作业跑py文件并分析】
fork()系统调用:创建新进程(相同程序的拷贝
wait()系统调用:延迟自己的执行
exec()系统调用:运行不同的程序

做对事Get it right。抽象和简化都不能代替做对事。

kill()系统调用:向进程发送信号signal,进程睡眠、终止或其他有用信息
ps看当前在运行的进程
top展示当前系统中进程消耗CPU或其他资源的情况
一个进程必须可以执行I/O和其他受限操作,又不能让进程完全控制系统,这时候可以采用不同执行模式:user mode和kernel mode
系统调用:允许内核小心地向用户暴露某些关键共——访问文件系统、创建和销毁进程、和其他进程通信,分配内存
执行系统调用需要执行特殊的trap陷阱指令,从而跳入内核并将权限级别提升为内核模式
陷阱如何知道在OS内运行哪些代码?可以在内核启动时设置陷阱表trap table
重新获得CPU的控制权
1.协作方式,等系统调用,比如时间过长或执行非法操作,就会把控制权还给操作系统
这时候如果进程无限循环,只能重启计算机
2.非协作方式,操作系统控制
正在运行的进程停止,操作系统中预先配置的中断处理进程就会运行,操作系统重新获得CPU的控制权,停止当前进程,启动另一个进程
上下文切换context switched 为当前正在执行的进程保存一些寄存器的值,并为即将执行的进程恢复一些寄存器的值
【重启】可以让软件回到已知状态,很可能是经过更多测试的状态,可以回收旧的或泄露的资源,否则将很难处理。
工作负载workload假设
操作系统中运行的进程,有假设:
1.每个工作运行相同时间
2.所有工作同时到达
3.一旦开始,每个工作保持运行直到完成
4.所有工作只用CPU,不执行IO操作
5.每个工作运行时间已知
调度算法
1.先进先出FIFO
2.最短任务优先SJF
3.最短完成时间优先STCF
4.轮转Round-Robin在一个十九篇(time slice调度量子scheduling quantum)内运行一个工作,然后切换到运行队列中下一个任务,反复执行直到所有任务完成
时间片长度必须为时钟中断周期的倍数,需要衡量其长度,以便摊销上下文切换成本,也不会让系统不及时响应
5.多级反馈队列MLFQ
用历史经验预测未来,如果工作有明显的阶段性行为
基本规则:
1)如果A优先级>B优先级,运行A
2)如果A优先级=B优先级,轮转运行A和B
3)工作进入系统时,放在最高优先级
4.1)工作用完整个时间片后降低其优先级
4.2)如果工作在其时间片内主动释放CPU,优先级不变
缺点:饥饿starvation问题
系统有太多交互型工作,会不断占用CPU,使长时间的工作永远得不到CPU
愚弄调度程序game the scheduler用卑鄙手段欺骗调度程序,让它给你远超公平的资源
如运行99%的时间片就主动放弃一次CPU,这样可以几乎独占CPU
计算密集的进程可能在某段时间表现为交互型进程
5)经过一段时间S就将系统中重新加入最高优先级
解决了饿死问题,但是S值的设定成为巫毒常量voo-doo constant,太高长时间工作会饿,太低交互型工作得不到合适CPU比例
4)工作用完某一层的时间配额,就降低其优先级
6.比例份额/公平份额调度程序:目标是确保每个工作获得一定时间比例的CPU时间,而不是优化周转时间和响应时间
彩票调度lottery scheduling:每隔一段时间,都举行一次彩票抽奖,决定接下来运行哪个程序
彩票书表示进程占据某个资源的份额。不断定时抽取彩票,从概率上获得份额比例。利用随机性,可靠又简单。
优点:
①可以避免奇怪的边角情况
②轻量,不需要记录任何状态
③很快,在运行速度要求高的地方适用
彩票转让ticket transfer一个进程可以临时将自己的彩票交给另一个进程
彩票膨胀ticket inflation一个进程可以临时提升或降低自己拥有的彩票数量
7.步长调度stride scheduling,确定性公平分配算法
选目前有最小行程值的进程,在运行之后将该进程的行程值增加一个步长(每个进程的步长可能不一样)
彩票调度不需要对每个进程记录全局状态,只需用新进程的票数更新全局的总票数,而步长是需要的!
8.多处理器调度
和单CPU的区别在于对硬件缓存cache的使用,和多处理器间共享数据的方法
有多级的硬件缓存一般会让处理器更快地执行程序。
缓存:小但快的存储设备,有内存中最热的数据备份
内存:大且有所有的数据,访问速度慢
缓存基于局部性locality,包括时间和空间。
时间局部性:一个数据被访问后,可能不久后会被再次访问
空间局部性:程序访问地址为x的数据,可能会紧接着访问x周围的数据
缓存一致性cache coherence,通过监控内存访问,硬件可以保证获得正确的数据,并保证共享内存的唯一性。
跨CPU访问如写入共享数据或数据结构时,需要用互斥原语比如锁,才能保证其正确性,没有锁时,即使有底层一致性协议,并发从队列增加或删除元素,依然不会得到预期结果
需要用锁保证数据结构状态更新的原子性
缓存亲和度:一个进程在某个CPU上运行时,会在该CPU的缓存中维护许多状态
9.单队列多处理器调度SQMS
简单,无需太多修改就可以把原有策略用于多歌CPU
缺点:缺乏可扩展性scalability,同步开销有限
10.多队列多处理器调度MQMS,如一个CPU一个队列,队列数量会随CPU增加而增加,缩合缓存争用不是大问题
但是,有负载不均load imbalance问题
让工作移动,叫做迁移migration,工作跨CPU迁移,可实现真正的负载均衡
系统决定发起迁移的技术叫工作窃取work stealing:工作量较少的队列不定期偷看其他队列是不是比自己工作多,如果目标队列比源队列更满,就从目标队列窃取一个或多个工作,实现负载均衡。
缺点:频繁检查其他队列,就会带来较高的开销,可扩展性不好。

也许目标不是找到最好的解决方法,而是为了避免灾难。 ——Lampson

《Computer Systems A Programmer's Perspective》

posted @ 2025-03-17 09:10  asandstar  阅读(69)  评论(0)    收藏  举报