operating_system_three_easy_pieces
这本书脉络很清晰,介绍的知识点也比较全面,分为三大模块(虚拟,并行,持久)来展开.而且英文内容也比较好理解,对准备学习操作系统的朋友还是比较推荐此书的.这里有一些同学正在进行中文翻译的工作,友情链接https://github.com/EmbedXj/OperatingSystems.ThreeEasyPieces
- 这篇博客只是针对我自己一些理解不深的和容易忘记的知识点做一个整理备份,用于以后的深入,并给准备阅读这本书的读者一个简要参考,具体内容就不展开了(实在是太多了orz….),本人初涉操作系统,关键点可能不能准确把握,见谅.
- 一二章是简单地介绍了三大模块的基本要点. 三四两章较简略地介绍了虚拟哈所涉及到的知识块,没有特别新的知识点,就不写了,基本看过csapp这本书的朋友都能理解.
第五章 进程API##
- 这里有一个点我看了翻译才确定书中的意思, 就是哪怕父进程先调用了, 因为它立即调用了wait()的system call, 所以一定会等到一个触发点(暂且这么理解吧)才能返回, 而这个出发点不能时父进程本身, 那只能是子进程的运行和结束, 所以不论如何都是子进程先打印,其次是父进程.
- fork()是同一程序产生动态的复制版本, 而exec()是将当前的程序转换为另一个程序且不返回,这意味着在exec之后的且属于同一进程的语句不会得到执行, exec()有六个子版本:execl(),execle(),execlp(),execv(),execvp()(具体抽空再补)
- strdup()功能:将串拷贝到新建的位置处, 其内部调用了malloc为变量分配内存,需要用free()释放相应的内存空间.
- shell被允许在调用fork()之后但在调用exec()之前运行代码
第六章 机制:有限的直接执行
- 虚拟化机制需要注意考虑性能和控制两点.
- 本章介绍了陷阱这一概念,它是用于不同系统状态间的切换的一种机制.
- 很好地将进程切换,内核与用户状态切换,操作系统三者结合起来讨论,比较清晰的梳理了三者之间的关系(相互依存,相互影响 ;-)
- 除此之外,作者所用的例子是基于xv6操作系统,所以一些代码会和之前的理解哟所出入,建议读者在阅读完此书后去学习MIT6.828这门课程,它就是通过对xv6全方面的剖析让你理解操作系统的各个核心部分.
第七章 调度:简介
- 本章的调度策略,介绍了周转时间这一概念.然后通过类似递进的方式介绍在调度方面的各类算法.First In, First Out (FIFO),Shortest Job First (SJF),Shortest Time-to-Completion First (STCF).以及其他的调度策略 Round Robin(RR)和Incorporating I/O等.此章结合对进程,线程,并行等的知识点理解会更透彻.
注: 后续很多章节的结构也和本章很类似,作者习惯于先介绍一个较为基础的模型,然后不断的 (抛出问题–>提出新模型) 这一方式来展开.
第八章 调度:多级反馈队列
- 本章是对上一章的另一个方面的拓展, 引入了优先级这一概念,描述了称为多级反馈队列(MLFQ)的调度方法。 它有多个级别的队列,并使用反馈来确定给定作业的优先级。历史是它的指南:注意工作随着时间的推移如何表现并相应地对待它们
第九章 调度:比例分配
- 本章介绍了比例共享调度的概念(个人认为是将优先级比例化的一个方式),并简要讨论了两种实现:彩票(谷歌翻译是这个2333…)和步幅调度。彩票以巧妙的方式使用随机性来实现比例分配; 步伐确实如此。虽然两者在概念上都很有趣,但由于各种原因,它们还没有作为CPU调度程序得到广泛采用。一个是这种方法并不特别地与I / O 啮合;另一个问题是,他们是否解决了机票分配的难题,即我们如何知道浏览器应分配多少票?通用调度程序更加优雅,因此可以更广泛地部署。因此,比例共享调度程序在某些问题的域中更有用相对容易解决。
第十章 多处理器调度
- 此章可以说是对并行化的一方面做了一个介绍,其实在csapp后面的章节也有介绍,其余的并行运算也会对此做出更为详细的讲解. 在本章看到了多处理器调度的各种方法。单队列方法(SQMS)可以很容易地构建和平衡负载,但本身很难扩展到许多处理器和缓存的可靠性。多队列方法(MQMS)可以更好地扩展并且很好地处理缓存效率,但是在负载不平衡方面存在问题并且更加复杂。 无论采用哪种方法,都没有简单的答案:构建通用调度程序仍然是一项艰巨的任务,因为小代码更改可能会导致较大的行为差异。(比如说你能够写出发挥自己电脑95%以上的性能吗…)
第十三章 抽象:地址空间
- 本章没什么新知识点…简单介绍了一个主要的OS子系统:虚拟内存。 VM系统负责向程序提供大型,稀疏的私有地址空间的错觉,程序将所有指令和数据保存在其中。 具有一些硬件帮助的操作系统将采用这些虚拟内存引用中的每一个,并将它们转换为物理地址,这些物理地址可以呈现给物理内存以便获取所需信息。 操作系统将立即为许多进程执行此操作,确保程序彼此保护,以及保护操作系统。 整个方法需要大量的机制(许多低级机制)以及一些重要的工作策略;
第十四章 内存API
- 这一章介绍了一些处理内存分配的API(大家都知道的那些…),所以没什么好介绍的。具体关于内存分配的知识点大家可以阅读我博客的一些关于内存知识点的整理.
第十五章 机制:地址翻译
- 在本章中,使用虚拟内存中使用的特定机制(称为地址转换)扩展了有限直接执行的概念。通过地址转换,操作系统可以控制进程的每个内存访问,确保访问保持在地址空间的范围内。这种技术的效率的关键是硬件支持,它为每次访问快速执行转换,将虚拟地址(进程的内存视图)转换为物理地址(实际视图)。所有这些都是以对已重新定位的流程透明的方式执行的;这个过程不知道它的记忆参考被翻译,造成一种奇妙的错觉。还介绍了一种特定的虚拟化形式,称为基本和边界或动态重定位。基础和边界虚拟化非常有效,因为只需要更多的硬件逻辑就可以将基址寄存器添加到虚拟地址,并检查进程生成的地址是否在边界内。基地和边界也提供保护;操作系统和硬件相结合,确保没有进程可以在自己的地址空间之外生成内存引用。保护当然是操作系统最重要的目标之一;没有它,操作系统无法控制机器(如果进程可以自由覆盖内存,那就说明可以覆盖陷阱表并接管系统orz…)。但是,这种简单的动态重定位技术存在效率低下的问题(如内部碎片等)。
这一章节的知识点还是需要读者自己去深入,查阅其他的相关资料会加深对此的理解。
第十六章 分段
- 终于来到segmentation了哈。是不是有时在linux命令行里运行程序的时候会报错segmentation fault?看完这章会对此理解更加深刻。
- 其实分段解决了许多问题,并帮助我们构建更有效的内存虚拟化。除了动态重定位之外,分段可以更好地支持稀疏地址空间,避免了逻辑分区之间的巨大潜在内存空间。它也很快,因为在硬件中进行算术分割需要简单且非常适合硬件;翻译的开销很小。一个边缘的好处也出现了:代码共享。如果代码放在单独的段中,则可能会在多个正在运行的程序之间共享此类段。但是,正如我们所知,在内存中分配可变大小的段会导致一些我们想要克服的问题。如上所述,第一个是外部碎片。因为段是变量化的,所以空闲存储器被切割成奇数大小的片段,因此满足存储器分配请求可能是困难的。人们可以尝试使用智能算法或定期压缩内存,但问题是根本的,很难避免。第二个也许是更重要的问题是分割仍然不足以支持我们完全通用的稀疏地址空间。例如,如果我们在一个逻辑段中有一个大但稀疏使用的堆,则整个堆必须仍然驻留在内存中或者可以访问。换句话说,如果我们关于如何使用地址空间的模型与底层分段的设计方式并不完全匹配,那么分割就不能很好地工作。
第十七章 自由空间管理
- 讨论了最基本的内存分配器形式。 这样的分配器存在于任何地方,链接到每个C程序中,以及在为自己的数据结构管理内存的底层OS中。 与许多系统一样,在构建这样的系统时需要进行许多权衡,并且您对提供给分析器的确切工作负荷了解得越多,他们就可以调整它以更好地适应该工作负载。 制作一个快速,空间有效,可扩展的分配器,适用于广泛的工作负载仍然是现代计算机系统中的一个持续挑战。
这里停一下,后续关于分页的内容可能阅读文字去理解不是很透彻,建议读者结合相关视频或者csapp中的图片来理解。
第十八章 分页:介绍
- 引入了分页概念作为我们虚拟化内存的解决方案。 与先前的方法(例如分段)相比,分页具有许多优点。 首先,它不会导致外部碎片,因为分页(通过设计)将内存划分为固定大小的单元。 其次,它非常灵活,可以稀疏地使用虚拟地址空间。
第十九章 分页:更快的翻译(TLBs)
- 本章引入的技术是利用了局部性概念(命中不命中23333),通过提供一个小的,专用的片上TLB作为地址转换高速缓存,大多数存储器引用有望在不必访问主存储器中的页表的情况下进行处理。因此,在通常情况下,程序的性能几乎就好像存储器根本没有被虚拟化,这对于操作系统来说是一个很好的成就,并且对于在现代系统中使用分页来说当然是必不可少的。然而,TLB不是一直有效的。特别是,如果程序在短时间内访问的页数超过了进入TLB的页数,程序将产生大量的TLB未命中,因此运行速度要慢得多。这种现象就是超出TLB覆盖范围,对于某些程序来说这可能是一个很大的问题。由于这个潜在的问题,人们已经研究了各种通过虚拟地址访问缓存的方法,从而避免了在缓存命中的情况下昂贵的翻译步骤。这种虚拟索引的缓存解决了一些性能问题,但也在硬件设计中引入了新的问题。
第二十章 分页:较小的表
- 介绍如何构建真正的页表; 不一定只是线性阵列,而是更复杂的数据结构(其实也不复杂,可以理解为索引再索引:)。 这些表格的权衡取决于时间和空间 - 表格越大,TLB未能得到服务的速度越快,反之亦然 - 因此结构的正确选择在很大程度上取决于给定环境的约束。 在内存受限的系统中,小结构是有意义的; 在具有合理内存量和主动使用大量页面的工作负载的系统中,加速TLB未命中的更大表可能是正确的选择。
第二十一章 超越物理内存:机制
- 介绍了访问更多内存的概念,而不是系统中实际存在的内存,并介绍了一些处理错误的机制。这样做需要页表结构更复杂,因为必须包含当前位(某种类型)以告诉我们页面是否存在于内存中。如果没有,操作系统页面错误处理程序运行以服务页面错误,从而安排将所需页面从磁盘传输到内存,可能首先替换内存中的某些页面,以便为即将交换的页面腾出空间。就进程而言,它只是访问自己的私有连续虚拟内存。在幕后,页面被放置在物理内存中的任意(非连续)位置,有时它们是存在于内存中的,需要从磁盘中获取。
第二十二章 超越物理内存:策略
- 本章有页面替换(和其他)策略的引入,这些策略是所有现代操作系统的VM子系统的一部分。 现代系统对时钟等简单的LRU近似进行了一些调整; 例如,扫描电阻是许多现代算法的重要组成部分,例如ARC。 抗扫描算法通常类似于LRU,但也试图避免LRU的最坏情况行为,我们在循环顺序工作负载中看到了这种行为。 然而,在许多情况下,所述算法的重要性已经降低,因为存储访问和磁盘访问时间之间的差异已经增加。 因为对磁盘的分页是如此昂贵,所以频繁分页的成本是高昂的。 因此,过度分页的最佳解决方案通常是简单的:分配更多内存。
第二十三章 VAX / VMS虚拟内存系统
本章展现了对整个虚拟内存系统的自上而下的视图。 通过一个具体的例子将前面的知识点串成一个模型,而在VAX / VMS这样的旧论文中发现的经典想法仍然影响着现代操作系统的构建方式。
不行了,写不动了,后续的内容其实大部分都是基于概念的理解,而且像并行章节的很多知识点个人觉得还是应该去实际敲一敲代码,去应用这些解决具体的问题会更有效果,而持久化部分,很多优化性的知识点是比较偏向cs方面的,相对来说文件系统方面的介绍对我的帮助比较大,后续等写操作系统的时候再补上吧。ps:个人觉得这些知识点还是通过写一个操作系统后对此的理解会更加深刻。
这里放一个问题与解答,仅供参考,我之前问过一个前辈关于操作系统的学习姿势,然后觉得不同专业的同学所需深入的内容不同,cs的同学可能更需要对底层的这些数据结构和算法更加深入(毕竟操作系统的各种优化基本上都是目前为止的一些达到极致的方案),而和本人(信安专业的)相同专业的同学可能跟需要对整体的整个架构,存在的问题点更加深入学习会帮助更大。:)