编写不朽的传奇
在PA的最后, 我们来做些好玩的事情.
Navy-apps之上的AM
一个环境只要能支撑AM API的实现, AM就可以运行在这一环境之上. 我们在PA3中已经使用libc和libndl实现了TRM和IOE的对应功能, 但并没有严格按照AM的API来实现它们. 如果把libc和libndl的功能按照AM的API包装成一台机器, 那么AM上的各种应用也可以运行在Navy-apps之上了.
框架代码已经准备好相应的功能了.
在nexus-am/am/arch/x86-navy
目录下已经准备了用于运行在Navy-apps之上的AM的框架,
但并未实现任何API. 你需要在x86-navy
中实现TRM和IOE的API,
这样就能支持绝大多数AM应用在Navy-apps上运行了.
我们在navy-apps/apps/am-apps
目录下准备了一个Makefile
脚本,
其中的APPS
和TESTS
变量可以用于控制对哪些AM应用进行编译,
这些AM应用会被编译到navy-apps/fsimg/bin/*-am
, 最后被包含到Nanos-lite的ramdisk中.
为了方便地使用这个脚本, 我们可以把am-apps
加入到Navy-apps的编译列表中:
--- navy-apps/Makefile
+++ navy-apps/Makefile
@@ -3,2 +3,2 @@
-APPS = init pal litenes
+APPS = init pal litenes am-apps
TESTS = bmp dummy events hello text
然后在nanos-lite
目录下更新ramdisk即可.
这样以后, 你就可以在Nanos-lite中加载这些AM应用了;
如果你之前成功运行了开机菜单程序, 可以修改navy-apps/apps/init/init.cpp
中的代码,
将这些AM应用加入到菜单中.
实现Navy-apps上的AM (选做)
为x86-navy
实现TRM和IOE, 然后在Navy-apps中运行AM应用.
不过在运行microbench的时候会出现_start()
并不位于0x8048000
的情况,
你需要在编译选项中加入-fno-reorder-functions
来修复这个问题.
什么? 不知道在哪个文件中加入? 那就自己了解一下项目的结构吧,
毕竟PA都快结束了, 现在还不知道项目结构就有点说不过去了.
如何在Navy-apps上运行Nanos-lite?
既然能在Navy-apps上运行基于AM的打字游戏, 那么为了炫耀, 在Navy-apps上运行Nanos-lite也并不是不可能的. 思考一下, 如果想在Navy-apps上实现CTE和VME, 我们还需要些什么呢?
诞生于未来的游戏
AM的精彩之处不仅在于可以方便地支持新机器, 加入新应用也是顺手拈来. 你的学长学姐在他们的OS课上编写了一些基于AM的小游戏, 由于它们的API并未发生改变, 我们可以很容易地把这些小游戏移植到PA中来. 当然下学期的OS课你也可以这样做.
我们在
https://github.com/NJU-ProjectN/oslab0-collection
中收录了部分游戏, 你可以在ics2018
工程目录下通过git clone
获得游戏代码.
由于我们已经设置好了AM_HOME
环境变量, 你就可以直接编译并运行了.
为了将它们自动收录到Nanos-lite的ramdisk中, 你可以进行以下修改:
--- navy-apps/am-apps/Makefile
+++ navy-apps/am-apps/Makefile
@@ -3,2 +3,2 @@
-APPS = coremark dhrystone hello microbench slider typing litenes
+APPS = coremark dhrystone hello microbench slider typing litenes ../../oslab0-collection
TESTS = videotest
这样以后, 你就可以根据上一小节的方法来将这些游戏运行在Navy-apps之上了.
RTFSC???
机智的你也许会想: 哇塞, 下学期的oslab0我不就有优秀代码可以参考了吗? 不过我们已经对发布的代码进行了某种特殊的处理. 在沮丧之余, 不妨思考一下, 如果要你来实现这一特殊的处理, 你会如何实现? 这和PA1中的表达式求值有什么相似之处吗?
展示你的计算机系统
目前Nanos-lite中最多可以运行4个进程, 我们可以把这4个进程全部用满.
具体地, 我们可以加载仙剑奇侠传, 打字游戏, slider和hello程序,
然后通过一个变量fg_pcb
来维护当前的前台程序, 让前台程序和hello程序分时运行.
具体地, 我们可以在Nanos-lite的events_read()
函数中让F1
, F2
, F3
这3个按键来和3个前台程序绑定,
例如, 一开始是仙剑奇侠传和hello程序分时运行, 按下F3
之后, 就变成slider和hello程序分时运行.
如果你没有实现Navy-apps之上的AM, 可以加载3份仙剑奇侠传, 让它们分别读取不同的存档进行游戏.
特别地, 如果你之前成功运行了开机菜单程序, 现在就可以加载3份开机菜单程序并绑定各自的按键. 在VME的支持下, 你可以在这3个开机菜单程序之间自由切换, 就好像在同时玩3个红白机游戏一样, 很酷!
展示你的计算机系统
添加前台程序及其切换功能, 展示你亲手创造的计算机系统.
必答题
分时多任务的具体过程 请结合代码, 解释分页机制和硬件中断是如何支撑仙剑奇侠传和hello程序在我们的计算机系统(Nanos-lite, AM, NEMU)中分时运行的.
温馨提示
PA4到此结束. 请你编写好实验报告(不要忘记在实验报告中回答必答题),
然后把命名为学号.pdf
的实验报告文件放置在工程目录下,
执行make submit
对工程进行打包, 最后将压缩包提交到指定网站.
欢迎二周目
你在一周目的PA中学到了什么? 二周目的时候就知道了: 二周目很顺利的部分就是你已经掌握的内容.
世界诞生的故事 - 终章
感谢你帮助先驱创造了这个美妙的世界! 同时也为自己编写了一段不朽的传奇! 也希望你可以和我们分享成功的喜悦! ^_^
故事到这里就告一段落了, PA也将要结束, 但对计算机的探索并没有终点. 如果你想知道这个美妙世界后来的样子, 可以翻一翻IA-32手册. 又或许, 你可以通过从先驱身上习得的创造力, 来改变这个美妙世界的轨迹, 书写故事新的篇章.
从一到无穷大
事实上, 计算机系统的工作只做两件事情:
- make things work
- make things work better
PA让大家体会了一次make things work的全过程. 具体地, PA以AM为主线, 从零开始展示了硬件, 运行时环境(操作系统)和应用程序之间同步演进的关系:
- TRM - 硬件有指令和内存, 几乎无需任何运行时环境, 就能运行所有的可计算算法
- IOE - 硬件添加输入输出, 运行时环境提供设备访问的抽象, 就能运行单一的交互式程序
- CTE - 硬件添加异常处理, 运行时环境添加上下文管理, 就可以支持批处理系统, 让用户程序顺序地自动运行
- VME - 硬件添加虚存机制, 运行时环境添加虚存管理, 就可以支持分时多任务, 让多个用户程序分时运行
这就是PA的全部内容.
当然, 还有各种原则和方法
除了"程序如何在计算机中执行", PA还展示了很多做事的原则和方法, 现在的你能回想起哪些内容呢?
如果你想不起来, 或者无法回忆起"程序如何在计算机中执行"的每一处细节, 那么也许你应该尝试一下独立完成二周目了. 坚持独立完成, 你将会对这些问题有全新的理解.
提示
既然你看到这里了, 就给你一个也许算不上奖励的奖励吧.
目前加入硬件中断之后, 各种基础设施就失效了. yzh在测试的时候曾经遇到过"加入硬件中断之后Nanos-lite随机触发assertion fail"的情况. 为了解决这个bug, yzh运用了以下原则: 对同一个用户进程来说, 是否加入硬件中断并不会影响其执行流. 然后把这个原则用于DiffTest中: 把加入中断前的用户进程指令序列作为REF, 加入中断后的用户进程指令序列作为DUT, 将两者进行比较, 总共花费了yzh约半小时就修复了这个原因很弱智的bug.
这个例子展示了自制轮子所需的必要条件:
- 明白"程序如何在计算机中执行"(中断对程序的影响)
- 随心所欲根据自己的需要对代码进行改造(如何抓取用户进程的指令序列)
如果你也在加入硬件中断之后遇到了调试困难, 但并没有想到上面的方法(无论这个方法对你是否有效), 那么也许你应该尝试一下独立完成二周目了.
但为了make things work better, 各种各样的技术被开发出来.
交互时代
就硬件而言, 摩尔定律预测了集成电路工艺的发展规律, 电路的集成度会越来越高. 这对计算机来说可谓是免费的午餐: 即使硬件架构师和软件设计师什么都不做, 芯片中的电路也会越来越小, 越来越快, 越来越省电. 电路工艺的发展直接推动了工作站和PC机的诞生, 搭载小型芯片的PC机开始走进寻常百姓家. 这意味着计算机不再像40-60年代那样只能进行核弹模拟, 密码破译等军事任务了, 它需要与普通用户进行交互, 于是需要一个支持交互的操作系统来方便用户使用, 当时最著名的就要数Unix和DOS了. 伴随着Unix的出现, 还有另一个流传至今的项目, 那就是C语言. 有了C语言编译器, 一些专业用户就可以开发自己的程序了. 办公和编程, 算是那个时代最普遍的应用了.
见证着摩尔定律的快速增长, 显然硬件架构师们并不会置身事外. 电路越来越小, 意味着同样大小的芯片上可以容纳更多部件, 实现更加复杂的控制逻辑. 从硬件微结构设计来看, 提升性能的一条路线是提高并行度, 从多级流水线, 超标量, 到乱序执行, SIMD, 超线程... CPU的并行度被逐渐挖掘出来; 提升性能的另一条路线是利用局部性, 于是有了cache, TLB, 分支预测, 以及相应的替换算法和预取算法... 在这些技术的支撑下, CPU等待数据的时间大幅降低, 从而能投入更多的时间来进行计算. 每当这些新名词出现, 都能把计算机的性能往上推. 计算机越来越快, 就能做越来越复杂的事情了. 一个例子是大大降低了计算机使用门槛的GUI, PC机上的分时多任务操作系统越来越普遍, 音乐, 视频, 游戏等休闲娱乐的应用开始大规模出现.
PC的足迹
上面的微结构技术都是在让一个处理器的性能变得更强(scale up), 而大型机和超级计算机早就用上了这些技术了, 它们在另一个维度上让自己变得更强: 通过片上互联技术(interconnect)把更多的处理器连接起来, 让它们协同工作(scala out). 于是有了SMP, ccNUMA, MPP, 以及各种互联拓扑结构. 同时为了高效应对多处理器架构中的数据共享问题, cache一致性和内存一致性也逐渐进入人们的视野. 为了适配片上互联技术, 可以管理众多处理器资源的集中式操作系统被设计出来, 随之而来的还有新的编程模型, 用于在这些强大的计算机上开发并运行应用. 过去诸如大气模拟, 物理建模等科学计算应用, 如今可以更快更好地在这些超级计算机上运行. 但片上互联技术要扩展规模较为困难, 大规模的处理器互联成本非常昂贵, 一般只有超级计算机能承受得起.
互联时代
如果没有互联网的普及, 计算机的发展估计就这样到头了. TCP/IP协议的标准化解决了互联网的传输控制问题, 让互联网从局域网迈向全球, 真正的因特网从此诞生. 因特网让人们变成了地球村的村民, 只要一根网线, 就可以轻而易举地访问到世界上任何一个角落的计算机. 另一方面, HTTP和URL的出现则真正让因特网广为人们所知, 网页浏览, 电子邮件, 文件传输, 即时语音等网络应用开始流行, 通过PC机的屏幕, 用户可以看到全世界.
除了PC机, 互联网的出现也让机器之间的互联成为了可能, 于是有了集群. 而集群需要一个可以管理众多计算机资源的分布式操作系统, 相应的分布式编程模型也开始出现, 过去在一个计算机上运行的任务, 现在可以编写相应的分布式版本来在集群中运行. 集群的出现一下子解决了系统扩展性的成本问题, 只要几个廉价的计算机和几根网线, 就能组成一个集群. 从此, 互联网公司如雨后春笋般诞生, 人类开始迈进互联时代.
集群的规模进一步扩大, 就成了数据中心. 由于集群实在太容易构建了, 有大量的机器却缺少可以运行的程序. 另一方面, 摩尔定律并没有停下脚步, 为了进一步挖掘处理器的并行度, 多核架构开始出现. 集群和多核架构造成了计算资源的供过于求, 数据中心的利用率非常低. 于是虚拟化技术诞生了, 在hypervisor的支持下, 一个计算机可以同时运行多个不同的操作系统. 这还不够, 为了进一步提高集群的利用率, 互联网公司开始以虚拟机为单位出租给客户, 让客户在其上自由运行自己的系统和应用. 后来, 硬件厂商在芯片中新增了虚拟化的硬件支持, 降低了虚拟化技术的性能开销, 虚拟机的性能和真机越来越接近. 云计算的大门从此打开, 越来越多的应用开始移动到云端.
此外, iPhone的诞生重新定义了手机的概念, 手机从过去的通讯工具变成了一台名副其实的计算机. 于是手机处理器和手机操作系统再次进入人们的视野, 和PC机相比, 手机上的处理器和操作系统还需要面对功耗问题的严峻考验. 手机应用开始大量涌现, 包括即时通信和移动支付在内的各种手机应用已经改变了用户的习惯. 各种应用也开始采用端云结合的运行模式, 现在我们在手机上点击一下微信应用的图标, 登录请求就会通过网络传输到云端, 被数据中心中的上百台服务器进行处理, 最后我们才会看到登录界面.
融合时代
互联网把人和计算机连接起来, 但这并没有结束. 摩尔定律还在发展, 处理器面积进一步减小, 以前把设备接入计算机, 现在可以把计算机嵌入到设备中了. 于是各种小型设备和物品也可以接入到互联网中, 这就是物联网.
随着接入互联网的人机物越来越多, 这些终端产生的数据也日益增加, 大数据时代拉开了序幕: 据IBM统计, 在2012年, 每天大约产生2.5EB(1EB = 10^6TB)的数据. 为了处理这些大数据, 人工智能和机器学习的概念再次流行起来, 但这一下子带来了海量的数据处理任务, 于是GPU和FPGA也加入到这场大数据的持久战当中来. 还有一支奇兵就是ASIC, 和CPU不同, ASIC是一个专用电路, 可以对某一应用进行深度优化. 以AI芯片为例, 与CPU相比, AI芯片可以提升成千上万倍的性能. AlphaGo的横空出世让人们感受到了人工智能的强大, 现在人工智能芯片也已经开始集成到手机中了, 人们也逐渐发现照片越拍越漂亮, 应用越用越智能.
在这个时代, 貌似没什么是不可能的. 计算机, 用户, 网络, 设备, 云, 数据, 智能... 这些概念之间的边界变得越来越模糊, 直接和应用打交道的用户, 也越来越感受不到操作系统和硬件的存在. 这反而说明了, 那些一脉相承的计算机基本原理已经在时代的发展中留下了挥之不去的烙印.
万变之宗 - 重新审视计算机
什么是计算机? 为什么看似平淡无奇的机械, 竟然能够搭建出如此缤纷多彩的计算机世界? 那些酷炫的游戏画面, 究竟和冷冰冰的电路有什么关系?
"一"究竟起源于何处? "无穷"又会把我们带到怎么样的未来? 思考这些问题, 你会发现CS的世界有太多值得探索的地方了.