常见问题(FAQ)

PA是什么意思

PA是Programming Assignment的缩写, yzh也觉得这个名字起得有点随意.

PA是不是组成原理/体系结构实验

都不是, PA不要求大家使用硬件描述语言进行编码, 而是通过C语言开发一款模拟器以及上层的软件(裸机运行时环境, 简易操作系统等). 与侧重于硬件层次的传统组成原理/体系结构实验相比, PA更注重计算机系统抽象层次的认识和理解.

PA是不是很难

PA是一个超硬核的编程实验, 其中的硬核体现在, 只有同时满足以下条件, 你才有可能比较顺利地完成PA:

  • 端正心态, 学会STFW/RTFM独立解决问题
  • 掌握工具, 知道用什么样的工具快速解决什么样的问题
  • 了解细节, 明白每一个文件每一行代码的行为
  • 系统编程, 熟悉计算机系统中每个模块之间的联系

如果之前没有受到过类似的训练, 即使是高年级的研究生也会感到一定的困难. 所以对绝大部分同学来说, 做PA就是一个吃苦的过程.

为什么要用这么变态的PA来折磨我

因为大家普遍都很菜, 按照目前的状态, 你毕业之后很可能无法在社会的毒打下存活. 以下例子展示了将来你可能会面对什么样的毒打:

你的导师/老板: 你来做一个xxx, 目标是达到yyy的效果.

讲义? 框架代码? 不存在的. 如果我们不提供讲义和框架代码, 让你写一个能跑仙剑的NEMU, 这就和你毕业后面临的任务很类似了.

这就是社会毒打你的第一招必杀技: 充满不确定性的未知问题. 如果你现在连链表都调不好, 显然你几乎无法胜任这些不确定的任务. 作为算是扛得住社会毒打的人, 我们知道你缺什么, 知道应该给你挖什么样的坑, 设置什么样的技能训炼, 你就会得到什么程度的成长.

所以我们设计PA来把现在的你毒打一顿, 让你受尽折磨, 吃尽苦头, 归根到底是为了让将来的你在求职时候更具有竞争力, 经受得起社会的毒打.

我将来不从事系统相关的工作, 就不会那么痛苦了

太天真了. 就算是应用程序, 几千个模块之间通过几万个API交互的场景都是家常便饭, 复杂性是社会毒打你的第二招必杀技.

现在是开源的时代, 开源在《十四五规划和2035年远景目标纲要》中首次被列入国家发展规划, 那我为什么不能参考别人的代码/心得/攻略来学习

你来上课来做实验, 就应该接受我们设置的训练, 而独立完成实验是训练最基本的要求之一, 参考别人代码就是违反学术诚信在新窗口中打开的行为, 针对这一点你没有任何理由讨价还价.

就算退一万步来讲, 你说参考别人是为了学习, 那你能写出比别人更好的代码作为学习的成果吗? 你要是真有这样的学习能力, 相信你也能够在遵守学术诚信在新窗口中打开的前提下自己独立完成实验.

同理, 阅读网上流传的心得和攻略, 也是属于违反学术诚信在新窗口中打开的行为, 因为你没有通过自己的努力和预期的训练来获得正确的答案.

为什么不能把代码/心得/攻略上传到公开的地方让大家学习

因为这违反了学术诚信在新窗口中打开. PA和其它项目不一样, 它本质上是一个课程作业, 你无法保证来看你代码的同学都是抱着纯洁的学习心态(我就看看我不抄). 如果有同学抱着抄袭的心态, 你的代码不仅会让他失去锻炼的机会, 而且还会破坏课程的公平性: 你一个bug调3天, 你同学1分钟就抄完了, 你甘心吗?

此外, 我们相信你的代码里面并没有太多值得大家学习的地方, 比如你的代码风格好看吗? 你设计的API合理吗? 和框架代码相比有什么新特色吗? 在你推荐自己的代码之前, 可以先看看一些优秀的开源项目. 如果你确实对自己的代码有信心, 不妨给yzh提建议, 如果你的建议很不错, 我们会把你加入到感谢名单中, 同时你的改进也可以一直在学弟学妹的作业中流传.

如果你上传代码只是为了托管, 那可以选择github的私人仓库.

同理, 将自己的心得和攻略上传到公开的地方, 也是属于违反学术诚信在新窗口中打开的行为.

所以, 你公开的代码/心得/攻略很大概率并不能从真正的意义上帮助大家学习, 相反而是在很多层面上伤害大家.

能不能公布阶段性的参考答案, 这样即使bug调不出来, 也能往后做

不能. 把代码写对是对码农最基本的要求, 代码还没写对, 就不应该往后做. 以后你进入社会, 如果你交付的代码给客户造成经济损失, 是要赔钱的. 所以要学会对自己写的代码负责.

我总觉得讲义写得不清楚

你毕业后进入公司/课题组, 不会再有讲义具体地告诉你应该做什么, 总有一天你需要在脱离讲义的情况下完成任务. 我们希望你现在就放弃"讲义和框架代码会把我应该做的一切细节清楚地告诉我"的幻想, 为自己的成长负起责任:

  • 不知道在说什么, 说明你对知识点的理解还不够清楚, 这时候你应该去看书/看手册
  • 不知道要做什么/怎么做, 说明你的系统观还是零碎的, 理解不了系统中各个模块之间的联系, 这时候你应该RTFSC, 尽自己最大努力梳理并理解系统中的一切细节
  • bug调不出来, 说明你不清楚程序正确的预期行为, 你需要RTFSC理解程序应该如何运行; 此外也说明你不重视工具和方法的使用, 你需要花时间去体验和总结它们

如果你发现自己有以上情况, 你还是少抱怨, 多吃苦吧.

当然, 如果你仍然觉得讲义写得不清楚, 可以联系yzh.

总是要求大家STFW/RTFM/RTFSC, 我有问题都不敢问了, 老师助教倒是轻松

老师助教不是你的保姆, 你需要先搞清楚哪些问题是你可以问的, 哪些问题是你应该自己解决的: 我们鼓励你提出关于方法层面的疑问以及对各种问题的探索性想法, 但不要直接让别人提供你想要的答案, 因为学会独立分析问题也是PA训练的一个重要环节.

一个我们不愿意回答的提问如下:

Q: 我的程序段错误了, 怎么办?
A: 机器永远是对的.

如果你确实需要一些调试相关的帮助, 那怎么办? 你需要展示你为了解决问题而付出过的努力, 当我们看到了你的努力, 也会认可你受到的训练. 例如:

Q: 我的程序在xxx的情况下段错误了, 我进行了以下尝试
* 首先我做了aaa, 现象是AAA, 我得到的结论是XXX
* 然后我做了bbb, 现象是BBB, 我得到的结论是YYY
* 我还做了ccc, 现象是CCC, 我得到的结论是ZZZ

综上, 我觉得问题可能出在yyy, 但我接下来没有思路了, 我的分析和理解是否正确? 或者我忽略了什么吗?

为什么用C语言写PA

首先C语言容易学, 可以给菜鸡们一个容易把编程能力补上的机会. 此外C语言的抽象少, 更接近机器, 更容易理解"程序如何在计算机上运行". 相对而言, 你很可能搞不清楚C++/python/java/scala/rust等各种语言特性背后的机制, 在调试代码的时候, 这会给你带来额外的挑战. 作为一个小型项目, 用C语言来写PA还是在可维护的范围的.

我发现自己做PA的用时明显大于讲义中预估的时间

讲义中的时间是按照"中等水平"同学的能力来预估的. 这里"中等水平"并不是指"程序设计课程总评80分以上", 而是指"心态端正, 编写过500行以上代码的单个程序, 并且懂得调试".

根据过去的情况, 绝大部分程序设计课程总评90分以上的同学都达不到我们所说的"中等水平"的标准. 所以忘了你的程序设计课程成绩吧, 对PA来说它并没有什么价值. (不过我们还是希望有一天这段话的描述不再符合实际.)

虽然程序设计课程成绩不能反映你们真实的编程水平, 但自己的编程水平是否扎实, 大部分同学还是心中有数的. 所以在这里我们也根据编程水平对讲义预估的时间进行调整, 得到一个更加可信的预估时间 (假设讲义上预估的时间是x小时):

  • 神: x / 5
  • 巨佬: x / 3
  • 大佬: x / 2
  • 编程基础扎实: x
  • 不会调试: x * 2
  • 不会写代码: x * 3
  • 即不会写代码又不认真做PA: x * 5

我们知道大部分同学无法客观地判断自己完成PA的真实用时, 所以拖延你就输了.

我觉得PA对像我一样的菜鸡很不友好

程序设计实验对菜鸡友好, 但为什么你做完之后还是菜鸡? 做一个对菜鸡友好的实验, 能力并不会得到提升.

如果你是菜鸡, 说明你之前该吃苦的时候没吃够, 现在比别人多吃苦就是应该的.

我连完成PA1都觉得非常吃力

PA1和计算机系统的关联度偏低, 它主要是为了测试大家的编程能力而设计的. 如果你连完成PA1都觉得非常吃力, 那你就要给自己敲响警钟了: 快去学编程吧.

我感觉大部分同学都无法在一学期内做完PA的全部内容

很正常, PA从一开始设计的时候就没有想过会让所有同学完成所有内容. PA的设计理念是把目标定得很高, 强迫大家往上跳, 所以你会明显感觉到PA和你做过的其它实验都不太一样: 只要你愿意付出足够的努力, 即使你没有完成所有的内容, 你也会感到自己各个方面的技能都有了明显的提升.

每年确实会有同学直接躺倒放弃而挂科, 但也总有为数不少一批同学能坚持到最后, 锻炼出专业程序员该有的素质. 大家的编程水平有高有低, 如果你自己都觉得编程能力不行, 那你就应该去把编程能力补上来, 在那之前就不要抱有"完成PA所有内容"的幻想了. 一个比较合适的目标是"独立完成PA1和PA2", 最后你仍然有机会通过课程.

坚持了好久还是搞不定, 我想放弃了

也许是你坚持的姿势不对, 来跟yzh或者老师助教聊聊吧.

我觉得应该搜集大家踩过的坑, 这样后面做的同学就会顺利一些

这种想法是不对的, 掉坑里然后自己爬出来是训练重要的一环, 只有吃苦头才会让你成长. 如果你不想以后掉坑里, 正确的做法是现在花时间踩坑吃苦, 让自己变强大, 而不是通过投机取巧的方式绕过那些你本应该接受的训练.

为什么我本地测试都是对的, 但提交到OJ总是无法通过

因为你的代码有bug.

PA的内容太丰富了, 我感觉没办法完全消化

所以PA值得二周目.

下学期的OSlab是不是比PA更难

在还没有PA的那个年代, jyy的OSlab是令人闻风丧胆的实验, 现在PA取代了这个位置. 你之所以觉得PA难, 一个主要原因就是前导课程没有给你足够的训练, 没有把你培养成一个素质合格的码农, 所以PA不得不额外承担这个角色.

从专业知识的角度来说, OSlab就应该比PA难. 但如果你已经在PA中训练出了码农应有的素质, 你也就已经准备好接受OSlab的挑战了.

PA和OSlab有什么区别和联系

  1. PA独有的内容: 上至运行时库函数和真实应用程序(仙剑, ONScripter等), 下至ISA模拟器的实现(寄存器, 指令, 分页机制等)
  2. OSlab独有的内容: 并发(锁, 同步等), 持久化(可靠性, 崩溃一致性等)
  3. PA和OSlab少量重合的部分: 上下文切换, 系统调用, 文件系统, 内存管理等. 但PA在涉及这些内容的时候是以广度优先为目标, 目的是通过设计一个最简单的模块, 把程序和计算机之前的关系串起来; 而OSlab会深入地展开这些内容, 比如ext文件系统, mmap等.

PA是OSlab的前导实验, 完成PA就会对操作系统有一个基本但不算深入的认识, 这时候再做OSlab, 上手就会更加顺利.

和大班的PA相比有什么区别, 哪个更难

大班PA是主线PA 2016版本的一个分支, 并且根据授课教师的想法进行调整. 随着主线PA的演进, 和大班PA的区别也逐渐增大. 鉴于"难"这个说法比较主观, 我们从另一个角度来展示两者的区别: 对于一个难点, 大班PA的设计理念是通过降低要求(提供提示甚至是代码)的方式来弱化它, 而主线PA的设计理念是呈现科学的方法来引导大家解决它.

所以从某种程度上来说, 大班PA降低要求的做法会对菜鸡来说会更友好, 但相对地, 全体学生在大班PA中受到的训练都会少很多. "计算机系统综合实验"课程对大班学生的少量抽样可以证明上述结论. 我们认为不应该为了照顾部分菜鸡而牺牲所有学生成长(吃苦)的机会, 所以主线PA没有选择降低要求, 而是让大家根据自身情况设置一个合适目标去努力.

我觉得PA有的设计不合理

欢迎联系yzh.