ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

腾讯后台开发笔试解析:C++与Linux核心考点拆解

腾讯后台开发笔试解析:C++与Linux核心考点拆解 说实话翻硬盘时翻出一份腾讯2015春招后台开发的练习卷我盯着看了几分钟脑子里全是当年刷题和笔试的画面。腾讯的后台开发岗在2015年那会儿几乎是C和Linux的天下这套练习卷覆盖的知识面放到今天依然能打很多考点在现在的校招笔试题里照样高频出现。它不是什么高深秘籍就是一份非常典型的、能反映大厂后台基础能力考察逻辑的样本。如果你正在准备校招、跳槽大厂后台岗或者自学后端想补基础这份卷子值得一练练完再看我下面的拆解会有收获。1. 2015年春招笔试生态腾讯后台开发到底在筛什么人现在回看2015年后台开发的笔试套路和今天比已经变了不少。那时候微服务还没彻底普及容器化生态远不如现在成熟腾讯后台岗位的主流技术栈还是C、Linux、TCP/IP、数据库那套硬功夫。笔试不是为了考倒你而是为了在海量简历里快速筛出基础扎实、能直接上手干活的人。1.1 为什么后台开发笔试绕不开“C Linux”组合2015年腾讯后台开发的核心业务场景包括即时通讯、游戏服务端、社交后台大部分核心模块都是C写的。C这门语言站在性能和可控性的制高点上但同时也对开发者的内存管理、编译链接、底层机制理解有很高要求。笔试里大量考察指针、内存布局、编译过程本质上是想确认你有没有能力在这套体系里写出稳定、高效的代码。Linux则是后台服务运行的基座。你写的C程序最终要部署在成千上万台Linux服务器上要处理高并发连接、排查线上问题不懂Linux命令和系统机制基本寸步难行。所以练习卷里出现操作系统、网络、Linux操作相关题目一点不意外。1.2 练习卷的题型结构与时间分配策略从练习卷的整体分布来看题型主要分三块选择题、填空题、编程题。选择题大部分落在C语法细节、操作系统原理、网络协议上每道题考察的知识点很单一但非常细腻经常在边缘语法和易混淆概念上设陷阱。填空题偏向输出结果或补全代码比如给你一段指针操作代码让你写出输出值。编程题一般是两到三道时间大概控制在60到90分钟。第一道通常是链表、二叉树、字符串处理这类经典数据结构题第二道开始加大难度可能出现海量数据处理、动态规划或者系统设计类的简化题。我当时给自己的时间分配策略是选择题最多40分钟不会的果断先标记跳过去编程题留足一个小时。笔试不是高考每道题都死磕只会让你在后面的编程题上仓促应付。先把能拿的分拿稳再回头啃难题这是笔试最基本的生存法则。提示面试后台岗前不要只在题库App上刷题。找一份像这样的完整练习卷严格按照考试时间做一遍才能真实暴露你在时间压力下的思维短板。2. 选择题里的操作系统与网络区分“背过”和“真懂”操作系统和计算机网络是后台开发笔试的必考板块也是不少人容易失分的地方。原因很简单这两块知识在平时写业务代码时用得不够直接很多人是考前突击背诵概念一到变形题就露馅。2.1 进程、线程与并发同步从题目到真实后台场景练习卷里几乎一定会出现的一道题是进程和线程的区别。这种题看似简单但选项里经常包含一些模糊表述比如“进程是资源分配的最小单位线程是CPU调度的最小单位”这句本身没问题但出题人会在其他选项里掺入错误表述比如“同一进程的多个线程共享独立的栈空间”“线程切换比进程切换开销一定更小”让你去辨别。这里我的经验是遇到这种题别只看字面要在脑子里建立一个完整的场景。比如线程为什么共享堆空间却拥有独立栈因为每个线程需要保存自己的调用栈和局部变量但堆上的对象是所有线程都能访问的。又比如线程切换开销真的“一定”比进程小吗不一定同一个进程内的线程切换确实比进程切换少了地址空间切换的开销但跨进程的线程切换比如Linux下线程本质也是轻量级进程开销未必小多少所以看到“一定”这种绝对化表述要格外警惕。并发同步的必考点是互斥锁、信号量、条件变量和死锁。练习卷里通常会出一道经典的死锁题给定两个线程分别持有锁A等待锁B、持有锁B等待锁A问最终状态是什么。答案当然是死锁。但更进阶一点它会考死锁的四个必要条件——互斥、持有并等待、不可剥夺、循环等待。这里我的建议是别死记四条而是去理解这四条如何对应真实的加锁流程。你在后台服务里写多线程代码时真正常见的是持有并等待和循环等待这就是为什么很多工程规范要求“按固定顺序加锁”。2.2 TCP/UDP细节那些必考的状态与参数网络部分TCP的三次握手和四次挥手是绝对的主角。练习卷里比较常见的出法有两种一种是直接问状态流转比如客户端发送FIN后进入什么状态、服务端收到FIN后返回什么另一种是给你一段异常场景比如客户端崩溃了服务端会发生什么这就涉及到TCP的保活机制和超时重传。TIME_WAIT是每次笔试几乎必考的状态。为什么主动关闭连接的一方要停留在TIME_WAIT状态2MSL有两点原因第一确保最后的ACK能到达对端如果丢失可以让对端重发FIN第二让本连接的所有报文在网络中自然消失避免影响后续使用相同四元组的新连接。放到真实后台场景里你负责的服务如果短连接特别多线上就会看到大量TIME_WAIT状态的连接这时候怎么调优就是另一个工程问题了。TCP的滑动窗口和拥塞控制偶尔会以选择题形式出现但比例不算太高。我建议你把重点放在“顺序号与确认号如何计算”和“拥塞窗口与慢启动阈值的关系”上。2015年的练习卷里出现过类似“发送方收到确认号100下一个要发送的字节序号是多少”的题答案应该是100因为确认号表示期望收到的下一个字节序号。这类题只要理解了TCP字节流的语义基本送分。UDP的考察点反而更集中一般只考无连接不可靠、头部开销小、支持广播多播以及和TCP的应用场景对比。比如问适合用UDP的场景选视频直播、DNS查询、游戏实时对战。真实后台开发中腾讯的音视频和游戏服务大量使用UDP或基于UDP改造的自研协议这个知识点完全不是纸上谈兵。重要整理网络题时尽量把每个协议状态和实际抓包对应起来。用Wireshark抓一次三次握手和四次挥手远比背十遍状态迁移图来得深刻。3. C/C内存与编译链接一道题暴露真实功底有些知识是面试时聊出来的有些是笔试时写出来的但C的底层功底往往一道选择题就能看出来。后台开发的技术栈核心是C笔试在这部分从来不手软。练习卷里关于内存、指针、编译链接的题目我建议你逐题吃透别只对答案。3.1 指针、内存布局和sizeof的经典套路每次笔试必有一道sizeof相关题目。比如定义char str[] hello问你sizeof(str)是多少。答案是6因为字符串末尾还有一个隐藏的\0。但如果定义char *p hellosizeof(p)在32位平台是4在64位平台是8这就考察指针大小与运行平台的关系。再进阶一点结构体内存对齐几乎是腾讯笔试的保留节目。比如一个结构体包含char a; int b; char c;问你sizeof(struct x)是多少。在默认对齐规则下答案是12而不是理论上的6因为int要按4字节对齐char c后面还要填充3字节让整个结构体大小是最大对齐数的整数倍。我当年第一次做这种题也栽过后来记了一个经验结构体大小一定是最大成员对齐数的整数倍每个成员偏移量必须是自身大小的整数倍。指针和引用的区别也是高频题。引用是别名不分配新内存指针是变量存的是地址。引用不能改绑指针可以随时指向别处。有一道经典辨析题函数参数传值和传引用的区别结合修改外部变量、拷贝开销、空值可能性来出。真正理解这些之后你才会明白为什么C代码规范里频繁强调“大对象用const引用传参”。3.2 编译链接与static/extern隐藏的必考题编译链接过程在2015年练习卷里出现过不少。一个C源文件到可执行文件经历预处理、编译、汇编、链接四个阶段。笔试题常问的是每个阶段做了什么事比如预处理阶段处理宏定义和头文件展开编译阶段生成汇编代码链接阶段解析符号和重定位。印象很深的一道题是多个源文件里都定义了同名全局变量链接时会发生什么答案是重复定义错误。但如果你给变量加了static修饰每个源文件各自持有一份互不影响这个区别很能体现对“内部链接”和“外部链接”的理解。static关键字在不同场景下的含义也是必考常客。static全局变量限定在文件内可见static局部变量延长生命周期到程序结束但作用域不变static成员函数不依赖对象实例可以直接通过类名调用。extern则相反它声明变量或函数在别的编译单元中定义用来实现跨文件访问。这些知识点看起来零碎但后台开发几乎每天都在跟它们打交道。比如你在一个模块里定义了全局配置项如果没加static又不加extern声明多文件编译时很容易出重复符号链接错误你要是把本该内部使用的函数写成非static还会污染全局命名空间这在大型项目里是实打实的工程质量问题。注意很多人在笔试时吃亏不是因为不知道某个知识点而是因为不知道题目在“变形”考察同一个知识点。比如sizeof和内存对齐放在一起考察static与链接放在一起考察单独背知识点是扛不住组合拳的。4. 编程题从“能写出来”到“写得漂亮”差在哪儿编程题是笔试的重头戏也是拉开分数差距的关键。练习卷里的编程题并不偏难怪但很考验代码的完整性和鲁棒性。很多人一道题能写出来但边界条件考虑不周、复杂度不达标最后只能拿到一部分分数。这才是最可惜的。4.1 链表、二叉树、哈希表常考题型与万能思路链表题几乎必考一道最常见的是单链表反转。这题本身不难但至少有三种写法迭代反转、递归反转、头插法。面试官想在笔试卷上看到的是你能否写出既清楚又无bug的版本。我建议把迭代反转写成标配核心逻辑就三步保存next、翻转指针、移动prev和current。边界条件是链表为空或只有一个节点别漏掉。二叉树的高频题包括前中后序遍历、层序遍历、求最大深度、判断平衡二叉树。练习卷里通常会出现“重建二叉树”或“最近公共祖先”这类稍难题。做二叉树题我的感觉是递归版本是最容易写对的但你要清楚递归调用栈的深度在极端情况下会爆栈所以涉及到深度时最好改成迭代版本或者在写递归时先说明假设。哈希表在笔试里往往不是单独考察而是作为优化手段出现。比如判断两个字符串是否字母异位词你的第一反应如果是双重循环那就是O(n²)的解法用哈希表统计每个字符出现次数一下就降到O(n)。后台开发对算法复杂度的敏感度非常重要因为线上服务处理的是海量请求一个O(n²)的循环在数据量上来后就是灾难。4.2 海量数据题目思路比代码更值钱2015年腾讯的练习卷已经开始出现海量数据处理的简化版题目比如“从100亿个数中找出最大的100个数”或者“大文件里统计出现频率最高的前10个词”。这类题在笔试里不要求你真在一台机器上处理PB级数据而是考察你有没有处理大数据问题的工程嗅觉。标准答案往往是大顶堆或者小顶堆。找最大的100个数就维护一个大小为100的小顶堆堆顶是当前第100大的数遍历完所有数据后堆里的100个元素就是答案。时间复杂度是O(n log m)其中m是堆的大小。如果你能顺便说清楚这样可以避免把所有数据全部载入内存就已经超过很多人了。但思路对了不代表满分你还要考虑数据如何分布。如果数据是分布式的能不能用MapReduce类似的思想做分片统计如果100亿个数分布在不同机器上每台机器算top100最后再做一次归并。这些是后台开发工程思维的一部分笔试卷上能体现出来说明你真的理解海量数据问题不是单纯算法问题。经验编程题写完后至少留三分钟自查。检查四件事边界条件处理了吗循环会不会死循环有没有使用未初始化的变量返回类型和题目要求一致吗我自己因为最后一项吃过亏——函数逻辑全对返回值却写错了一道题直接扣掉一半分。5. 数据库和Linux实操笔试里最容易拉开差距的部分很多人复习腾讯后台开发笔试时把时间全压在C和算法上结果在数据库和Linux题目上栽了跟头。这部分题量不一定大但每一道都在考察你是否具备真实的后台开发工作能力。毕竟写代码只是基本功部署、运维、排查问题才是日常。5.1 索引与事务SQL题背后的设计意图数据库题目主要涉及MySQL。练习卷里常考的SQL题包括查询优化、索引选择、事务隔离级别。有一条很容易混淆的经典题在什么情况下索引会失效比如对索引列使用函数、隐式类型转换、左模糊匹配、OR条件中包含非索引列。我当时复习时把每种情况都整理成一条笔记面试时再被问到就能脱口而出。事务隔离级别的考察也很典型MySQL默认的隔离级别是REPEATABLE READ而Oracle默认是READ COMMITTED。这个差异在后台开发里经常被拿来讨论因为由隔离级别引起的脏读、不可重复读、幻读问题在不同数据库下表现完全不同。练习卷中常见的是给一个业务场景让你判断用了哪种隔离级别会出现什么现象然后问如何用间隙锁或者MVCC解决。索引字段设计这道题练习卷的出现率也很高。比如一张用户表有id、user_id、mobile、created_at几个字段现在有一条查询条件是“根据手机号查用户信息”你会不会在mobile字段上建索引答案是分情况如果这个查询是高频且区分度高的那必须建如果这张表只是批量导入用的临时表那建了反而增加写开销。后台开发做表设计索引不是越多越好而是在读写之间找平衡。5.2 Linux命令和排查思路怎么在笔试题里体现工程经验Linux部分的笔试题目通常分两类一类直接考命令参数比如查看端口占用用什么命令、查看进程的CPU和内存占用用什么命令。答案分别是netstat或ss以及top、ps。但更值得关注的是第二类综合题给你一个线上故障场景让你列出排查思路。练习卷里出现过类似这样一道题一台服务器CPU使用率接近100%你如何定位是哪个进程的哪个线程导致的完整思路是先用top查看是哪个进程CPU高再用top -H -p PID查看该进程内哪个线程占用高接着把线程ID转成十六进制用jstack或gdb查看线程栈确定是代码里哪一块逻辑在空转或死循环。这套排查路径直到今天都适用它在笔试卷上考察的不是单一命令的记忆而是你是否真的处理过线上问题。另一个经常出现的是查看日志。比如应用日志在滚动你想实时追踪最新写入的日志用tail -f你想从一个非常大的日志文件里找出所有包含“ERROR”的行并统计出现次数用grep ERROR app.log | wc -l。这些命令单独问谁都会但放在一个综合场景里就能看出你是不是只会在本地跑跑demo。提示不要小看笔试里的Linux题更不要只背命令不带场景。建议在本地虚拟机或云服务器上主动制造几个故障——比如故意写一个死循环、疯狂创建线程、把磁盘空间占满然后逐个用命令排查这个过程比背一百道面试题都有效。6. 做完这套练习卷之后我建议你这样复盘练习卷做完了对完答案就扔到一边这是大多数人复习效率低的核心原因。笔试题目本身就包含大量可挖掘的知识关联做一遍的价值和深度复盘一遍的价值至少差三倍。我分享几个自己复盘这类练习卷的方法都是当年踩过坑之后总结出来的。6.1 不要按题目复盘按知识点网格复盘我做错一道题后不会只看正确答案就翻篇而是把这个题涉及的知识点在脑子里画一张网。比如做错一个TCP的TIME_WAIT题我会把所有相关知识点全部过一遍TIME_WAIT出现在四次挥手的哪个阶段、主动关闭方是谁、为什么需要2MSL、MSL是多少、TIME_WAIT过多会有什么影响、如何调整内核参数、短连接场景和长连接场景各有什么表现。这种复盘方式看似慢但效率极高。一道选择题错过去等于把TCP连接的整个生命周期重新理解了一遍后面再遇到TCP相关的题目无论怎么变都能应对。整理成文档后考前复习也很方便比重新翻一整套练习卷快得多。6.2 把笔试题反向改造成面试题自己考自己练习卷里的编程题和简答题本质上都是面试的素材。我在复盘时会做一件事每道题都问问自己如果我是面试官我会顺着这道题追问什么。比如笔试考了“进程和线程的区别”我就问自己为什么线程切换比进程切换开销小协程和线程的区别是什么一个进程最多能创建多少线程创建线程失败通常是哪个资源不足这些追问一旦能答上来说明对这个知识点的理解才算真正到位。编程题也一样。比如我写完了单链表反转我会继续想如果链表有环呢如果是双向链表呢如果要求原地反转不能开新空间呢能不能用递归写并分析空间复杂度这样一道算法题就变成了一组面试连环题从笔试到面试的整个备考链路就打通了。练习卷只是一面镜子真正决定你水平的是看到镜子里的自己之后愿意花多少时间去弥补差距。2015年的题目和现在相比考察的底层能力并没有本质变化把基础打扎实走遍大厂都不怕。
返回列表