
Day34按计划今天该把操作系统、数据库、计算机网络的复试高频考点统一过一遍再把容易卡壳的手撕代码环节梳理清楚。复试和初试不一样初试看你能不能在卷子上把题写对复试看你能不能当着几位老师的面把思路讲明白、把代码写利索。很多人在初试能拿高分但一进面试教室就开始语无伦次原因不是知识储备不够而是没有把“题库式记忆”转换成“问答式输出”。Day34的笔记我干脆以面试追问为主线把常见考点、容易踩的坑、现场的应对习惯都串在一起写给自己也分享给正在准备复试的朋友。1. 今天复盘什么复试全局的“查漏”思路1.1 复试和笔试的考察角度差在哪初试的题目有标准答案阅卷老师看的是你结论对不对、步骤全不全。复试不一样尤其是面试环节老师问一个问题并不是只想要一个“是或否”而是想看你的思考路径。比如问到进程和线程的区别普通答案背一背就能答但老师大概率会追问“那进程切换为什么比线程切换开销大开销到底在哪”这就是复试与笔试最大的区别它不仅考你知道什么还考你能否把知识点串起来。我在Day34的复盘里专门把考纲里那些零散概念重新按“原理-应用-代价”三个维度梳理了一遍。原理是回答“它是什么”应用回答“它解决什么问题”代价则回答“为什么不能随便用”。很多同学能背出进程的五态模型但被问到“在实际系统里为什么要引入就绪队列和阻塞队列”就卡住其实就是缺少“应用和代价”这一层。1.2 今日主题拆分与复习节奏进入复试准备期后我一般把一天拆成三个时段上午留给操作系统和数据库这类偏原理的科目下午集中计算机网络与手撕代码晚上专门做模拟提问和错题复盘。Day34的重点放在了四块进程调度与死锁、数据库索引与事务、TCP可靠传输与HTTPS握手、手撕链表和二叉树。这四块几乎是理工科复试提问命中率最高的区域无论你报的方向是系统结构、软件工程还是人工智能老师都有很大概率在综合面试环节从这些基础问题切入。这天的笔记我没有继续“抄书式”地堆知识点而是换了一种方法把每个高频问题写成“老师可能会怎么问”的形式再在旁边写一版“两分钟内怎么有条理地回答”。比如“进程与线程的区别”这题我会分成三点回答——资源所有权的角度、调度开销的角度、地址空间隔离的角度——每一点都带一句具体场景这就比单纯背概念要自然得多。2. 操作系统高频考点调度、死锁与内存管理2.1 进程状态机与调度算法从SRTF到多级反馈队列复试问操作系统几乎避不开“进程调度”。老师问调度算法时最喜欢的方式是给一个具体场景比如“有一批长短不一的作业你选哪种调度算法为什么”如果你只背了名称说不出背后的权衡这道题就会显得很干。常见的算法里FCFS实现简单但对短作业不友好容易产生“长作业占住CPU短作业一直等”的护航效应SJF能最小化平均等待时间但难点在于系统不知道未来哪个作业更短适合批处理而不是交互式环境时间片轮转保证了响应时间但时间片太小会导致频繁上下文切换CPU的有效利用率反而下降。实际面试里最常被追问的其实是多级反馈队列。原因很简单它把前面几种算法的优点整合在了一起也更贴近真实操作系统。多级反馈队列的核心思想是“用历史表现推断未来”新进程先放入最高优先级队列时间片用得越快、降级越快在低优先级队列里时间片更长但得到的调度机会也更少。回答这类问题时最好补充一句“它解决了SJF需要预知执行时间的问题同时保证了交互型任务的响应速度”这一句就能把算法和实际工程场景挂上钩。我做的笔记里还画了一张简单的状态流转表来帮助记忆进程从创建进入就绪就绪被调度进入运行运行因等待I/O进入阻塞运行时间片结束又回到就绪阻塞在事件完成后重新进入就绪。面试时如果被问到“一个进程从创建到结束经历了哪些状态”直接照着这个顺序讲不丢细节。2.2 死锁判定与“哲学家吃饭”的例子死锁条件几乎是必背的——互斥、占有且等待、不可剥夺、循环等待四个条件缺一不可。但复试喜欢往深了问既然缺一不可那打破其中一个条件是不是就能预防死锁比如把打印机改成“所有人都必须先申请到所有资源才执行”就不会产生循环等待但代价是资源利用率急剧下降甚至可能造成饥饿。这种“打破条件”的思路要有但面试官更希望听到你能比较预防、避免、检测与恢复这三层策略的差异。检测与恢复里最典型的算法是死锁检测算法它本质上是在资源分配图上不断尝试给进程分配它需要的资源看能否让所有进程都完成。复试题常让考生模拟一个资源分配场景判断是否处于死锁状态。这里有一个容易踩的坑分配图中如果有“进程等待的资源正被另一个也处于等待链中的进程持有”那多半就是死锁但如果有资源被释放的路径则可能只是暂时阻塞。哲学家就餐问题则用于考察“互斥与并发”之间的平衡。传统的解决办法是给哲学家编号奇数先拿左叉子、偶数先拿右叉子从而避免循环等待。还有限制同时最多四人入座的方案以及用AND型信号量一次申请所有资源的方案。面试时建议先讲清楚问题的本质是“多个进程持有部分资源又申请新资源”再给出至少两种解决思路老师一般就会满意。2.3 页面置换与LRU的工程实现内存管理这块最容易被追问的是页面置换算法。OPT是最优解但它需要未来知识现实中做不到FIFO实现简单却存在Belady异常——物理页框变多缺页率反而上升这种现象刚开始复习的同学很难理解需要解释因为FIFO不考虑页面的实际使用频率某些常被访问的页面反而被优先换了出去。LRU则是利用“最近的历史访问”来预测“最近的将来”虽然有近似性但在多数场景下表现优秀也是工程中最常用的策略。面试官如果问“LRU在真实系统里怎么实现”很多人会背“哈希表加双向链表”这套答案却没有理解为什么要用双向链表。在链表中间删除节点时如果是单向链表必须从头遍历找到前驱节点才能完成删除时间复杂度是O(n)双向链表因为每个节点都存了前驱和后继指针删除任意节点都是O(1)。哈希表负责O(1)地查找这个页面是否在缓存中链表负责维护访问顺序。回答到这里最好再补一句“访问某个页面时把它移到链表头部缓存满时移除链表尾部节点”这样整个实现思路就完整了。补充一个小技巧面试聊到缓存淘汰时可以主动提一下优化方案比如用Clock算法作为LRU的近似替代。它只需要一个循环数组和一位引用位成本远低于真正的LRULinux内核里某些场景就是这么做的。这会让面试官觉得你不只会背书还对真实系统有了解。3. 数据库与事务被追问最频繁的索引、并发与范式3.1 索引为什么用B树而不是哈希数据库索引是复试问答的“必争之地”。很多同学背结论“InnoDB用B树索引”但老师紧接着问一句“为什么不用哈希索引”就答不上来。核心原因要从两类索引的适用条件来看哈希索引对等值查询非常高效一次散列就能定位到目标但一旦遇到范围查询、前缀模糊匹配、排序操作哈希就无能为力了因为哈希表的物理布局不保证键的顺序。B树是一棵有序树所有叶子节点通过链表串联范围查询只需要找到边界节点然后顺序遍历即可这就是数据库选它做主索引的根本原因。如果再往深一点可以补充B树和B树的区别。B树每个节点既存索引键又存数据B树的所有数据都集中在叶子节点内部节点只存键值。这样一来B树的内部节点更小同样大小的页能容纳更多键树的高度更低同时所有查询都必须走到叶子节点查询路径固定性能更稳定。复试时候凡是被问到“为什么用B树”把“低树高、支持范围扫描、数据都在叶子层便于顺序I/O”这三点答齐基本就够了。聚簇索引和非聚簇索引也是一对高频追问点。聚簇索引的表数据物理上按索引键排序一个表只能有一个这样的索引非聚簇索引的叶子节点存储的是主键值而非行数据通过非聚簇索引查数据时可能还需要回到主键索引再查一次这就是“回表”。如果面试官问怎么优化可以考虑“覆盖索引”——让查询涉及的列都包含在索引中从而跳过回表步骤。3.2 事务ACID、隔离级别与MVCC事务这一块先背熟ACID原子性、一致性、隔离性、持久性。复试的难点通常是“这些特性分别由哪些机制保证”。原子性依赖Undo Log回滚时用日志里的旧数据覆盖回去持久性依赖Redo Log即使崩溃也能通过重做日志恢复隔离性靠锁或多版本并发控制一致性可以看作前三个特性的综合结果。把“机制和特性一一对应”比只背概念要扎实得多。隔离级别这部分表格会比文字更清楚隔离级别脏读不可重复读幻读读未提交可能可能可能读已提交否可能可能可重复读否否可能InnoDB通过间隙锁可避免可串行化否否否复习时要特别留心“读已提交”和“可重复读”的区别。前者是每次语句开始前生成一个新快照后者是事务第一次读取时生成快照整个事务期间都读这个快照因此同一个事务里两次读到的结果相同。这也是MVCC在InnoDB中的实际表现。面试如果问到幻读别只回答“多出来几行”最好补一句“InnoDB在可重复读级别下通过间隙锁和临键锁来避免幻读因此MySQL默认的“可重复读”实际上比SQL标准里的“可重复读”更严格”。3.3 范式设计在实际业务中的“取舍”第一、第二、第三范式和BCNF是复试爱考的简答题。第一范式要求列不可再分第二范式要求非主属性完全依赖主键第三范式要求非主属性不传递依赖主键。光背定义容易被问“实际设计时要不要追求最高范式”就不好答。工程上的通用结论是“不要盲目追求高范式”。范式高的好处是数据冗余少、更新一致性好但查询往往需要更多表连接性能会下降。实际项目里经常会在第三范式基础上做一次反范式化比如在订单表里直接存“用户昵称”这个冗余字段就是为了减少每次订单列表查询都去关联用户表。面试时主动说出这样的权衡比背概念更亮眼。我在笔记里给自己留了一句记忆口诀“依赖完全、无传递、列不可再分”。每次设计表的时候都拿这三条快速过一遍先保证达到第三范式再根据业务查询场景决定要不要增加冗余列。这个思路在笔试数据库设计题里也很好用能在短时间内给出一个既规范又可落地的表结构。4. 计算机网络的经典连环问可靠传输与安全4.1 三次握手、四次挥手与TIME_WAIT三次握手是复试常客但很多人只背“SYN、SYNACK、ACK”这三步却不知道为什么握手必须是三次而不是两次。关键点在于“确认对方接收能力”和“防止失效连接请求突然到达”。如果只有两次握手服务器无法确认客户端的接收能力是否正常也无法辨别网络上残留的旧连接请求是否有效第三次握手正是客户端对服务器同步报文的一个明确确认让双方都确认彼此的收发能力。四次挥手有两个值得展开的细节。第一断开连接时FIN和ACK被拆成两步是因为TCP是全双工的两端各自独立关闭自己的数据发送通道收到对方的FIN只代表对方的数据发完了自己这一侧可能还有数据要发。第二主动关闭方会进入TIME_WAIT状态并等待2MSL这个问题的标准回答是“保证最后的ACK能到达对方同时让旧连接报文在网络中彻底消失”。面试官如果再追问“TIME_WAIT过长会不会有影响”可以补充一句“主动关闭方在高并发短连接场景下可能出现大量TIME_WAIT连接占用本地端口这时需要从应用层考虑长连接或调优系统参数”。4.2 从HTTP到HTTPSTLS协议流程复试里网络安全的题也常出现。最常见的一个问法是“HTTP和HTTPS有什么区别”。常规答案是“HTTPS比HTTP多了加密”但不够完整因为HTTPS还带来了身份认证和完整性保护。HTTP报文以明文传输容易被窃听和篡改HTTPS在HTTP和TCP之间加了TLS层通过证书验证服务器身份、通过对称加密保护传输内容、通过消息认证码或AEAD算法保证报文没有被篡改。TLS握手流程如果能在面试中流畅讲出来绝对加分。我的表达顺序是客户端先发送ClientHello带上支持的TLS版本、加密套件列表和随机数服务器返回ServerHello选定加密套件和服务器随机数同时下发证书客户端验证证书后生成预主密钥用服务器公钥加密传回双方各自用三个随机数通过密钥导出函数生成会话密钥之后客户端发送Finished报文用协商出的密钥加密服务端验证成功后也发送自己的Finished握手完成。这一段说清楚基本就能证明你是真的理解而非背稿子。有一个容易忽略的点证书验证不仅仅是看证书是否过期而是要验证证书链是否可信、域名是否匹配、是否被吊销。如果老师追问“中间人攻击为什么能生效”就是因为客户端没有正确验证服务器证书或者客户端信任了攻击者自己伪造的证书。回答时把这个逻辑链讲出来比只背概念效果好得多。4.3 TCP拥塞控制与真实场景的映射拥塞控制的四个算法——慢启动、拥塞避免、快速重传、快速恢复——几乎年年考。慢启动的意思是拥塞窗口从一个小值开始每收到一个确认就增加一个MSS实际上拥塞窗口指数增长一旦到达ssthresh就进入拥塞避免窗口线性增长出现丢包时传统TCP认为发生了拥塞将ssthresh减半并把拥塞窗口重置回初始值。现代实现通常还会走快速重传和快速恢复收到三个重复ACK就立即重传丢失的报文同时把拥塞窗口减半而非归零避免链路吞吐的断崖式下降。复试题偶尔会出计算题比如“假设RTT为100ms初始拥塞窗口为1个MSS慢启动每轮窗口翻倍问经过400ms后窗口多大”。这类题只要搞清楚慢启动按RTT轮次增长就不会错400ms就是4轮1变2、2变4、4变8、8变16注意如果ssthresh是8到第四轮就不能再翻倍而是进入线性增长。把ssthresh这个边界条件看清楚计算题基本不丢分。5. 手撕代码与笔试机试把“懂”变成“写对”5.1 必练的数据结构链表、二叉树、图的遍历复试机试虽然各校难度不同但使用频率最高的还是链表、二叉树和图的遍历三类。链表题目的核心是“指针操作准确”出现在面试题里最多的包括反转链表、合并两个有序链表、找中间节点、判断是否有环。二叉树题目主要围绕前中后序遍历的递归与非递归写法、层序遍历、最近公共祖先、二叉树的最大深度等。图的题目则集中在DFS和BFS以及用这两种方式解决的连通分量、拓扑排序、最短路径问题。复习这几类时我给自己定的标准是“不写注释也能在15分钟内独立写出来并且能跑通几个自测用例”。因为面试现场的紧张感会让简单的手误被放大熟练度直接决定代码质量。建议整理一个自己的模板库树的递归模板、树的迭代遍历模板、BFS模板、DFS模板、拓扑排序模板。模板不要背别人写的要自己推导一遍再定稿这样就算紧张也容易还原出来。5.2 常见手撕题目与解法拆解手撕代码如果只练一道我会选“反转链表”。它的迭代写法看似只有三行核心逻辑却非常容易出错def reverse_list(head): prev None curr head while curr: next_node curr.next # 先保存后继节点 curr.next prev # 改变指针方向 prev curr # 移动 prev curr next_node # 移动 curr return prev这道题真正的考点在于“改变指向之前先保存后继节点”这个顺序。很多人在白板上写的时候先执行了curr.next prev结果后续节点全丢了。面试时写这类题建议先在注释里标出三步走保存后继、反转指向、前移指针这样既提醒自己也让面试官看到你的思路。二叉树非递归中序遍历也是高频题用显式栈模拟系统栈def inorder_traversal(root): result [] stack [] curr root while curr or stack: while curr: stack.append(curr) curr curr.left # 一路向左 curr stack.pop() # 弹出最左节点 result.append(curr.val) # 访问 curr curr.right # 转向右子树 return result写这道题时最常见的错误是忘记在循环条件里加入or stack导致树遍历完后还有节点在栈里时循环提前退出。另一个易错点是在弹栈之后没有继续处理右子树逻辑上少了一个分支。对这个模板还不够熟的话不妨在纸上手工模拟一棵四层二叉树跑一遍比盯着代码看更有帮助。5.3 面试现场写代码的四个习惯现场写代码和平时刷题是两回事有些习惯最好在复试前就刻意养成。先说第一件动手前先和面试官确认输入输出。比如反转链表你可以问“允许修改原链表吗返回新链表的头节点就可以吧”确认需求看起来是小动作但能避免写完后发现方向跑偏面试官也会觉得你沟通能力不错。第二件是边写边说。不一定每行都解释但要在几个关键决策点说一句原因比如“这里我设置一个dummy节点方便处理头节点被删除的场景”“这里用栈而不是递归是为了避免链表过长时栈溢出”。这样面试官可以在你写代码的过程中同步理解思路。第三件是写完自己举测试用例。最简单的是“空链表、单节点、两个节点、常规多节点、全相同值节点”这五类能快速覆盖大多数边界问题。第四件是用词准确。不管你说的是伪代码还是实际可运行代码都要先说明“我先给一版伪代码理清思路”再转成正式实现。这种“先思考、再动手”的模式本身就符合面试官对工程师的期待。6. 复试面试混战连接知识点、简历与软技能6.1 把笔记整理成“面试答辩卡”复习到Day34我发现光靠反复翻笔记效率已经开始下降于是换了一个方式把每一个高频知识点浓缩成一张张答辩卡正反面各一个方向。比如操作系统这一面只写“进程调度算法对比”列出算法名称、适用场景、权衡点、常见追问背面则写“如果老师问到这里我额外能讲的一点延伸”给每条准备一个加分素材。这个方法的核心是“预演输出”。面试本质是一场口头表达测试光看懂、听懂不叫会能说清楚才叫会。准备答辩卡时我建议把每道题的回答时段控制在2分钟左右内容分为“一句话结论—原理展开—例子说明”三段。比如“什么是死锁”这题一句话结论是“多个进程因竞争资源而相互等待的僵局”原理展开是四个必要条件例子就可以拿“两个进程分别持有一把锁又都想获取对方手里的锁”来打比方。这样练上三轮口头表达的稳定性会提高不少。6.2 被问到不会的问题时的应对思路复试最怕的其实不是被问倒而是被问倒之后手足无措。我在Day34笔记里专门给自己写了一个应对策略先不急着回答把问题拆解成自己熟悉的部分。比如老师问“你了解一致性哈希吗”如果你只知道哈希取模就可以大大方方说“我对一致性哈希的具体实现了解不够深入但就哈希取模在节点增减时需要大量迁移数据的问题而言一致性哈希的核心思路是让每个节点负责一段哈希环上的区间从而减少迁移量”——这样的回答既承认了不了解的部分也展示了已有认知的迁移能力。这里要特别提醒千万不要不懂装懂。老师在这个领域多年很容易识破含糊其辞的答案留下最差的印象。正确的说辞是“这里我了解得还不清楚我的理解是……如果哪里不对请老师指正”然后用几句简洁的话表达思考而不是硬编。面试官想要的不是完美的候选者而是能保持诚实和学习姿态的候选者。6.3 机试与项目复盘的时间分配很多学校复试分为笔试、机试和综合面试三部分Day34复盘时我把剩余时间的分配调整为“机试写题和项目复盘各占三成专业课口答占四成”。为什么机试要单独留出比笔试更多的比重因为笔试的知识点可以通过短期记忆突击但写代码的熟练度不可能靠背诵获得需要每天保持手感。项目复盘也不只是把项目背景和技术栈背一遍而要能回答“你在项目里遇到了什么困难”“为什么选这个方案而不是另一个”“测试是怎么做的”。我在笔记里给自己的项目写了三个层面的串讲第一层是一句话讲清楚项目做什么第二层是30秒讲清楚核心模块的设计第三层是准备三个可能被追问的细节比如某个接口的响应时间是多少、是否做过压力测试。把这些准备好面试时谈项目的状态就和平时聊天一样自然。7. 今日笔记小结Day34留给我自己的东西Day34的收获不只是一堆知识点的重新梳理更重要的是我发现了自己之前的复习方式存在一个明显问题一直在“输入”很少做“输出”。复试与初试最大的不同就在这里所有的知识储备都必须落实到一句口头表达、一段现场代码、一次临场反应上。从今天开始我的学习方法改成“读一遍、写一遍、说一遍”读懂了不算能在纸上默写出来才算能在纸上写出来不算能对着镜子用口语讲明白才算。最后再分享一个小技巧录音复盘。我用手机把自己模拟回答的音频录下来回放时能明显听出哪些地方停顿太久、哪些表述逻辑混乱。这个方法听上去有点笨但实际训练效果非常好。如果你时间紧张至少保证每天用20分钟回答三个高频问题整个人的面试状态会在两周内发生变化。Day34的笔记不是终点它更像是给自己按下的一次“切换模式”的按钮。