====更新日记====
update1: 20160211 更新了部分标题, 增加了lab1的介绍。
===============
闲扯
呐, Introduction to Computer Systems (课号15213) 就是鄙校 CMU 的招牌课程了。 15213 在 CMU 是如此受欢迎, 以至于几乎每个人都会选这门课; 实在选不到的人会在暑假上这么课的 online 版。 相当巧合的是, 15213 正好是 CMU 的邮编(zip code)。 因此,这门课在 CMU 又被亲切地称为『The course that gives CMU its ZIP !』
相信我,不要被这个“Introduction”骗到: 15213 跟国内那些“大学计算机基础”完全不是一个量级。 这门课的内容非常扎实, 可以说是涵盖了计算机系统的方方面面; 配套的编程练习也相当有挑战性, 绝对不会让人有昏昏欲睡的感觉。
213 还有配套的教材 —— 大名鼎鼎的 CSAPP。 如果要列一个“程序员必读书单”的话, 那么CSAPP一定会出现在前三的位置 ; ) 课程内容跟教材是完全对应的: 每一章着重讲解一个重要的概念, 并配以练习题。 CSAPP 第一章介绍了计算机执行一个程序的过程;第二章介绍了计算机存储各种数据的方式,包括整型数和浮点数。第三章是一个重点,介绍了现代计算机的堆栈结构。本章涉及很多汇编语言,因此可能会有点难啃。第四章分析了内存性能。第五章教你提高程序的性能。第六章忘了。第七章忘了。第八章是关于系统中断的。第九章涉及内存管理,包括虚拟内存,内存分配等等。第十章到第十二章浅尝辄止讲了concurrency和network programming的基础内容。
难度
213 的难度中等,每个周大约需要15小时时间。 相信我, 这15小时绝对没有水分。 对于那些计算机基础不太好的人来说,甚至可能需要20-30个小时。
如果仅仅是把教材里的东西讲一遍,那么 213 绝对不会成为 CMU 的神课。 213 最精华的部分在于它的七个 lab。 在上课+看教材的基础上,再独立将这七个 lab 搞定, 那么编程功力一定会有很大的提升哈哈哈。
labs
lab1: datalab
datalab 的核心是 bit manipulation。 为了让学生更好地理解数据在计算机内的存储形式, datalab 要求用有限数量的操作符来实现一些位操作。 比如, 在我那个学期, lab1 里有一道题目是将一个浮点数乘以0.5。 以下是这道题目的要求以及我的解答:
/*
* float_half - Return bit-level equivalent of expression 0.5*f for
* floating point argument f.
* Both the argument and result are passed as unsigned int's, but
* they are to be interpreted as the bit-level representation of
* single-precision floating point values.
* When argument is NaN, return argument
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
unsigned float_half(unsigned uf) {
/* use masks to extract the sign, exp, frac of a fp number
* if exp is 0xFF, means infinity or nan, just return uf
* if exp is 0 or 1, according to the table of denormalized and normalized fp numbers
* shift the temp right by 1, meaning that divide by 2, and if frac's last two bits are 11, there is a round problem, deal with it
* in general cases, just subtract exp by one indicate half
*/
int s_mask = 0x80000000;
int exp_mask = 0x7F800000;
int frac_mask = 0x007FFFFF;
int s = uf & s_mask;
int exp = (uf & exp_mask) >> 23;
int frac = uf & frac_mask;
int temp = 0;
int mask_1 = 0x00FFFFFF;
if (exp == 0xFF) return uf;//inf and nan
else if (exp == 0 || exp == 1) {
temp = (uf & mask_1) >> 1;
if ((frac & 3) == 3) temp ++;
return s | temp;
}
else return s | ((exp - 1) << 23) | frac;
}
上完这个课之后, 我还看了一下同学们的代码, 真是八仙过海各显神通。 为了搞定这个作业, 大家毫不留情地用了各种奇技淫巧。 有的人甚至去查服务器(每个lab的评分都是在服务器上进行的)的 CPU 型号, 试图找到 CPU 的某条隐藏指令, 从而用更少的操作符数量来实现函数功能。 说到这儿, 你可能会问, 为什么大家这么拼? 功能实现了不就行了吗? 这就涉及 213 的另一个有趣之处: scoreboard 机制。
简单来说, 每次作业都有一个对应的scoreboard, 上面显示每个人的分数。 对于那些有性能要求的作业(比如lab1), scoreboard 会根据代码的性能来排名; 对于那些没有性能要求的作业, scoreboard 则会按照提交时间的早晚来排名。 为了能在 scoreboard 上占到一个好名次, 常常有人通宵达旦地优化自己的代码。 刚才提到的lab1, 满分是63分。 我用大约190个操作符便达到满分, 而排名第一的居然只用了108个操作符, 简直令人发指。
扯远了。 总而言之 lab1 对于理解计算机数据的格式有相当大的帮助。 做完作业后, 我对 int 以及 float 的理解加深了一个层次, 在后来的面试中碰到 bit manipulation 的题一点都不会害怕, 反而会感到一点兴奋。
lab2: bomb lab
bomb lab 的内容是『拆炸弹』。 当然, 这里的炸弹不是真的炸弹, 而是一个编译好的 linux 程序。 要想拆掉这个炸弹, 需要连续输入六个特定的字符串(key)。 如果你输错了任何一个 key, 程序就会“爆炸”, 并自动登录课程服务器, 扣除一定的分数。
拆弹过程需要用到简单的逆向工程。 具体方法是用 gdb 来调试。 为了避免扣分, 需要在爆炸模块前面设置断点 —— 这样一来, 即使输错字符串, 程序也不会运行到爆炸模块。 为了找到那key, 学生得一行一行分析反汇编出来的汇编代码, 搞明白代码的控制流, 并找到以字符串形式存储在程序中的key。 整个拆弹的过程非常惊险刺激, 玩得我简直停不下来 XD。
lab3: attack lab
第三个lab比较邪恶,是 stack overflow 攻击。 这个lab包含两个程序: 正常的程序 A 和恶意的程序 B。 正常情况下, 在执行程序 A 的时候, 是不会调用程序 B 的。 我们的任务是让程序 A 执行程序 B。 怎么样, 是不是听上去很黑客很厉害? 具体的内容就不剧透了。 总之, 搞定这个lab之后, 我对x86的stack frame以及程序的调用过程有了深刻的了解。
lab4: cache lab
第四个lab的目的是实现一个Least Recently Used Cache (LRU Cache)。
Cache 是提升计算机存储系统性能的利器。 要理解cache,首先要理解现代计算机的存储 hierarchy: 寄存器-内存-硬盘。 从上往下, 价格越来越便宜,存储容量越来越大, 但速度越来越慢。
既然寄存器最快, 那么为什么不全部采用寄存器作为存储器呢? 原因很简单: 寄存器的价格太过昂贵。 反之亦然: 我们也不能一味贪图便宜而全部用硬盘, 否则整机性能会大打折扣。 因此, 我们需要在价格和性能之间做一个tradeoff, 为不同的计算机配置不同的存储器系统。
lab5: shell lab
shell lab 的任务是实现一个 shell。 不过, 这个shell是高度简化的。 我们不需要 build from scratch; 我们可以在现有的bash的基础上写自己的shell。 涉及的知识有 system call,interrupt handler 和各种 signal。
lab6: malloc lab
传说中最难的一个 lab。 任务是写一个 malloc 函数。要实现一个 malloc 是不难的; 难的是benchmark。 以后再说。
lab7: proxy lab
第七个lab是proxylab。这个proxy需要支持 http1.0 协议。做完这个lab后对多线程有更深入的理解了哈。
相关资源
配套slides
CMU 15213课程网站上可以下载到。
视频
CMU 貌似没有加入任何 MOOC,也不允许学生上课时录影,因此没法在网上找到213的教学视频。但是,coursera上有一门 Hardware Software Interface课,用的是213的教材,lab也是完全照搬213。据说老师讲得非常好(UW的老师),甚至比CMU版本还要好。想学的话推荐去注册这门课。