从来没有想到自己的求职之路会这么顺利, 第一次投阿里就拿到了offer, 以前一直都是做好被刷的准备的...
3月31号晚上收到了来自阿里的正式offer, 签下录取意向书, 粗略算了一下, 从2012年9月份正式入学进入计算机系到2015年3月签下阿里offer, 大约两年半的时间, 这期间有很多人值得感谢: 磊哥, 立萍, 宋艺, 兴华老师... 发生了很多事儿: 从最初的懵懵懂懂到后来的立志进入像阿里一样的一线互联网企业, 从对计算机一窍不通到有自己的目标和兴趣爱好, 从不知道技术博客是啥到个人博客的访问量超过40W... 也学习了很多内容: C++, Linux, 数据结构与算法, 计算机网络(TCP/IP), 操作系统(OS)...
磊哥一直想让我写下这次面试的经过, 同时也记录一下这一年来准备招聘的过程, 很多有意思的事儿如果现在不写下来以后很快就忘了, 何况看了这么多的面试经验, 现在到了"回馈社会”的时候了, 但是一直拖着不知道怎么开始, 这一拖就到了5月份, 这篇博客陆陆续续写了半个多月, 感觉今天应该告一段落了, 不然总有新的东西加进来,这篇博客是永远写不完的...
由于很多朋友和大神学弟对我找工作的准备过程以及面试经历比较感兴趣, 我就分别谈一下自己的这两段经历吧:
我是在2013年11月份中旬遇到磊哥的, 当时磊哥刚刚拿下阿里巴巴的offer, 意气风发, 我越俎代庖请磊哥给我们这些学弟学妹做交流讲座的详细经过在我的另一篇博客《我的2013 -岁月划过生命线》(链接)有详细的记录, 在此我就不再赘述了, 不过后来我又找了磊哥好几次, 聊了很多, 也收获很多, 下定决心一定要进入阿里之类的一线互联网公司, 后来磊哥也一直鼓励并帮助我进入阿里, 因此, 我一直把磊哥当成为命里的贵人.
我的准备工作大致分为五方面内容: C++, Linux, 数据结构与算法, 计算机网络(TCP/IP)和操作系统. 如果一个本科生能够把这五方面的基础打得比较坚实再加上稍稍一点儿运气, 拿下互联网的offer是不在话下的, 另外如果你实力够强的话, 那仅需的一点儿运气也是不需要的, 在此我引用671学长的一句关于面试的经典: ”面试 = 运气*(50-n)/100 + 实力*(50+n)/100, n=f(x),x即实力,n与x成正比关系,这就意味着: 你实力越强,对运气的依赖性越低,所以实力才是非常重要的一个环节.”, 下面分别介绍一下我所准备的五方面内容:
C++:
C++被我称之为飞机中的战斗机, 我对C++是情有独钟的, 他功能非常强大, 尤其是其与Linux操作系统结合, C++灵活的语法, 再加上Linux强大的平台支持, 让人感觉有种手握核武器的感觉[不过今天(4月28号)获悉自己在阿里实习被分派到了YunOS手机操作系统部门, 以后要主攻Java了...], 这方面我读过的经典的书有《C++ Primer》,《Effective C++》,《深度探索C++对象模型》与《STL源码剖析》,其实在面试阿里的时候《STL源码剖析》这本书是还暂时未读完,而且我的简历上面也没写我读过STL源码, 但是面试官仍然问了很多这方面的内容,如:关联容器的典型实现原理, vector/list的实现, 迭代器失效的问题, string的三种实现方式等, 面试官对STL实现的看重可见一斑; 另外《深度探索C++对象模型》也是面试官常问的内容之一,像虚函数的实现机制, 重载的实现原理什么的都是常问的, 在网上流传着一段关于本书的书评, 感觉比较有意思(链接); 《Effective C++》中的内容在我面试时没怎么问到, 但是我个人感觉trains技法是比较难,而且属于比较重要且常用的内容, 因此大家也需要悉心准备一下. 这方面的书要多读几遍, 不要异想天开的认为这些书只读一边就能够完全理解, 经典之所以叫经典, 就是无论你第几次读都能找到新感觉!
Linux:
关于Linux部分是值得大书特书的, 我感觉这次之所以面试这么顺利, 很大一部分是Linux帮了我的忙. 我个人把Linux的内容分为两部分:一是Linux开发环境,一是Linux编程:
1) Linux开发环境: 在这部分我认为最主要的是学习Linux这个操作系统平台的思想(Linux很多方面都与Windows有所不同, 如一切皆文件等), 以及使自己适应Linux的命令行,其他的都是次要的. 因此这方面的内容是比较好学的. 这方面比较重点的内容是: Linux常用命令, Vi/Vim使用, 软件管理, 用户管理, 权限管理, 进程管理, Shell编程以及常用开发工具(如gcc/g++, gdb, make)的使用等. 这方面的内容我比较推荐两本比较经典的书《鸟哥的Linux私房菜》,《Linux Shell脚本攻略》, 但是对于这种实践性课程,光看书是不够的,而且有时仅仅看书是很枯燥的,因此我在此给大家推荐一部”李明Linux视频教程”(链接),大家结合着书与视频练习, 不会感到枯燥; 李明老师对于Linux无论是基础知识还是高级应用的功力都十分精湛,听课时既能学到知识又能拓宽视野, 因此这部视频我看了两遍, 而Linux的笔记就写了两遍, 我把所有的听课时的笔记都整理发布到了博客上(链接); 我原来看的是第一版的视频, 系统是基于CentOS 5.5的,后来李明老师又出了第二版, 当然第二版增加了很多内容, 组织也更加清晰合理, 总的说第二版是比第一版更好的, 但是珠玉在前, 我仍然是对第一版情有独钟, 因此第二版仅挑着第一版照顾不到的内容看了看.
另-建议各位读者朋友: 在刚刚开始学习Linux时, 最好在电脑中只装一个Linux, Ubuntu也好, CentOS也罢(不过我个人还是比较推荐使用Ubuntu作为桌面操作系统), 此时最好完全摒弃Windows的观念, 日常只用Linux, 最多不超过一个月就开始对Linux与命令行有感觉了!
2)Linux编程: 这部分当然还是首推W.Richard Stevens的三部书了,《Unix 环境高级编程》, 《Unix网络编程-卷I-联网套接字》,《Unix网络编程-卷II-进程间通信》, 但是这三本书内容深刻, 而且卷帙浩繁, 组织庞大. 俗话说"没有三两三, 休想过梁山”, 没有非常熟练的Linux/Unix操作系统基础, 没有一定的Linux编程基础, 这三本书是不容易读懂的, 因此在这三部饕餮盛宴之前, 我首先推荐一碟开胃小菜《Linux程序设计》. 但是这四部书的内容并不一定需要全部读完的, 《Linux程序设计》中有三分之一的内容是不需要读的(像终端控制, gtk/gnome编程什么的), APUE的重点是前18章, UNP卷I重点是TCP与UDP编程的内容, UNP卷II主要讲解System V与Posix两种IPC进程间通信的方式, 但是这两种IPC方式的内容大致是想通的, 像两者都有共享内存, 信号量, 消息队列等, 因此学会Linux/Unix编程的思想与原理就好, API的具体用法多查一下MAN手册就好了, 有了这些基础之后我建议再读一读游双老师的《高性能Linux服务器编程》, 这本书深入浅出的讲述了编写Linux服务器程序的理论基础与实践经验, 而且还介绍了如何编写服务器的测试程序以及开发Linux服务器程序的常用工具等很有实际意义的内容, 非常值得一读; 而且这部书还重点介绍了Linux中的重型武器Epool, 并与select/pool进行了应用层与理论层的对比, 这是APUE与UNP所不具备的, 且这也是面试的重点之一! 对于学有余力的朋友我在推荐一部Linux与C++编程领域的神作《Linux多线程服务端编程 -使用Muduo网络库》, 陈硕老师在书中不仅介绍了使用C++进行Linux分布式网络服务器编程的常用技法, 而且还总结了使用C++进行编程的经验教训, 而且这些问题还都是面试时常考的(像string的几种实现模式等), 无奈本人两方面的基础较浅, 只能挑着一些比较简单的主题研读一番..
和学习Linux开发环境一样, 我也比较推荐在学习Linux编程时不要仅仅看书, 我在刚刚开始学习Linux编程时, 由于大三课程较紧, 因此只是读书很少实践, 到后来感觉这样学习效果很差, 到后来在我准备自己的面试项目MyHttpd的时候竟然不敢动手去写, 因此在这儿我着重推荐C++教程网的两部视频"Linux系统编程”与"Linux网络编程”, 后来我结合视频与书籍, 不断的去实践, 并将重要的内容总结成博客并发表出来(链接); 当然C++教程网也出了很多其他内容的视频, 像"跟我一起学C++”, "自己动手写FTP”等,内容很充实, 能够学到的知识很多, 但是都是价格不菲, 而且我只看了系统编程与网络编程部分, 因此其他的我不便推荐, 希望以后有时间能够把C++教程网的视频都能够学完, 到时候自己的编程功力肯定能够提升一个层次. 还有就是现在传智播客也开设了C++课程, 我在淘宝上买了他们那边第三期和第四期的视频,而且我也仔细学习了他们的Linux基础编程与Linux高级编程的视频教程,但是说实话真是乏善可陈,而且有很多内容我感觉传智播客的老师是在学了C++教程网的视频再现炒现卖给他们学生上课的, 因此在此我并不推荐看这些视频(由于我拿不出法律可依的证据, 只是对比他们两方的授课内容相似, 即使错误之处亦相同, 因此如果不相信的朋友就权当我是在意淫吧).
数据结构与算法
这方面我准备的时间最长, 花费的心血较多, 从2012年入学直到现在(2015年5月份)我都一直在持续不断的补充自己数据结构与算法方面的知识. 这方面我感觉比较经典的书是《数据结构与算法-维斯(C++版)》和《算法导论》, 维斯的书非常的棒, 无论是理论还是实践都有非常多的亮点, 而且这部书还有C语言版与Java版,总有一款适合你(*^_^*); 《算法导论》大名鼎鼎,其内容就不用我赘述了, 而且我也只读了部分的内容, 像链表,树,图,红黑树等,在此也是没有资格推荐的.
面试时链表,树, 排序与Hash的内容考察较多, 尤其是与STL的内部实现相结合来考察(既考察了C++常用技法, 又考察了数据结构与算法的内容,一举两得). 关于数据结构与算法部分的面试,有三部书不得不推荐一下《剑指offer》,《编程之美》和《编程珠玑》, 还有一个网站LeetCode(链接). 这些内容都是都是我从很多面经中总结出来的, 尤其是LeetCode, 里面一些很赞的面试真题, 没事的时候建议刷一下.
最后关于”数据结构与算法”的学习, 我建议最好在网上找些这方面的视频结合着书看, 因为这部分比较费脑子, 书看累了的时候就可以看些视频, 敲敲代码, 帮助消化.而且在我看来, 一个准备在IT领域有所作为的程序员/工程师, 数据结构与算法的是无论何时都是不能放下的, 在这儿我推荐一篇Google工程师的博客, 我记得当时我看完之后颇受感染, 不知道大家有什么感受(链接).
计算机网络(TCP/IP)
关于TCP/IP,面试的时候问得颇多, 类似TCP的11种状态, TIME_WAIT状态的原因, TCP三次握手的原因等. 可以看出网络层与传输层(重点是TCP)的内容是重点, 如果按照优先级对TCP/IP进行排序的话, 应该是传输层>网络层>链路层, 关于计算机网络, 我看的书有《计算机网络(谢希仁著)》与《计算机网络联考复习指导(王道)》,《TCP/IP详解-卷I》只挑了重点的几章内容(本来是打算把这整本书仔细研读一遍的, 但由于时间不足, 这个愿望一直未能实现, 打算等到在阿里实习结束,本科毕业之前一定好好的把这部经典读完). 在面试结束后的一个月内, 我自己根据这次面试的经过以及结合自己读到的面经的内容, 自己总结了四篇TCP/IP的博客, 个人感觉有志于进入互联网公司的读者朋友可以读一下(链接).
操作系统(OS)
关于操作系统, 重点在于进程管理与内存管理这两章, 再加上SPOOLing等一些零零碎碎的内容. 操作系统我感觉比较不错的书籍有《现代操作系统》,《操作系统联考复习指导(王道)》与《计算机操作系统(汤子瀛)》;《现代操作系统》我只看了有限的几章,《操作系统联考复习指导(王道)》我读了两遍, 估计大家也看出来了, 这本书与前面提到的《计算机网络联考复习指导(王道)》都是考研书, 但是但是考研类的书往往对课本内容的重点总结的比较精确. 像这本操作系统, 我就感觉对OS重点总结是比较精确, 当然经过压缩之后有些问题也是有些阐述不明(像内存管理中的页式管理和段页式管理等), 但其他的内容感觉总结的确实是挺到位的(因此我的几篇操作系统的博客就是以王道的书为蓝本,再结合面试中常考的知识点写成的, 不过现在还未发表, 因为排版整理的工作还未完成, 不过他们会最终发到这个目录下面:链接). 最后一本书是我们的上课时的课本,个人感觉这本书还是挺靠谱的, 但是有些内容有些啰嗦, 学院派气味很浓, 有些问题本来举个例子就可以阐明的却用了一大段晦涩难懂的描述性文字, 让人似懂非懂.
我学习操作系统与计算机网络的有一点心得是: 感觉两者很类似, 都是内容很零碎, 但又都不很难; 因此, 他们的学习最好与系统编程/网络编程结合起来学习, 这样就会有一番更深深的体会.
另-如果大家对Linux内核比较感兴趣而且实力足够的话,建议读一下《Linux内核的设计与实现》或《Linux内核源代码情景剖析》,前者内容较难, 我只读了有限的几章, 而后者的总页数超过1000页, 这两部书有很大的毅力来读的...
3月7号(2015年)磊哥把我的简历推到YunOS, 3月12(周二)晚七点参加一面, 3月13(周三)下午三点参加二面, 隔了一周3月20号(周三)晚八点参加三面, 3月24号(周日)参加四面, 3月30号收到offer.
前面说过, 我从来没有想到这次面试会这么顺利, 很早以前我就做好了前几家面试会被打击的准备, 而且这次面试又是这么仓促, 从简历推上去到真正面试只有三四天的准备时间, 还要一直提心吊胆不知道啥时候一个电话打来就要面试,终于在磊哥的一顿催促之下, 阿里那边的人在我返校之后的第五天晚上,开始了面试:
一面:
一面问得问题有: (1)TCP三次握手过程, 与为啥需要采用三次握手; (2)TCP TIME_WAIT状态的原因; (3)C++ 虚函数机制(C++对象模型); (4)C++ Static关键字; (5)Select/Poll/Epoll的异同(使用与内部实现方面); (6)C++迭代器失效问题(iterator原理); (7)map/set容器的实现原理(红黑树知识+STL容器内部原理);
前面的这几个问题比较简单, 回答的都比较流畅, 估计面试官打算在最后一题发难吧, 最后一个系统设计题难度陡然提高, 一下子就没了感觉, 题的内容是 "现在有两块内存, 一块10G设名为A, 一块20G设名为B, 现在A中数据已满, 但还有新的数据到来, 因此只能转向B写入, 但是还需要把A中的内容做数据迁移, 移动到B, 那么现在问题来了: 如何保证在不打断新数据写入的前提下, 将内存A中的数据完整的迁移到B, 即不能出现在A中数据迁移完成之前B内存满了或者打断新数据输入的情况”, 这个问题纠缠了十多分钟, 我尝试了从数据结构和操作系统的角度去解决这个问题, 但都被面试官否决了, 直到现在这道题我仍然不知道该如何解决.
二面:
二面问得问题有: (1)我的博客的访问量的问题(估计是暖场吧); (2)Linux 伙伴堆算法(slab)实现的原理, 以及与普通内存分配相比有什么优势(Linux内核); (3)Linux 高并发的实现, 线程池的实现思想, 怎样处理高并发(根据项目来问); (4) Linux 写一个并发测试程序; (5) 如何实现一个String, 他的内存是长什么样的(STL内部实现);
记得当时二面面试官打电话过来的时候还在上课, 跟老师匆匆说明情况之后就找了一间空教室开始面试. 与一面面试官的和蔼不同, 二面面试官刚开始问得问题就咄咄逼人(相对较难),而且在我回答问题时还曾经不止一次被他打断. 由于题目相对较难(也可能是我自己水平不足)感觉需要思考一段时间才能回答, 而且有好几个问题是我以前没有接触过的(像题目2, 题目4, 题目5), 我只能凭自己的理解去回答, 面试还未结束, 我就感觉这次面试的结果有点儿悬, 可能过不了这一关了... 但当时心里倒是很坦然, 由于刚开始就没有打算能够通过, 因此也就没有那种"天生我材必有用”或那种"此处不留爷,自有留爷处,处处不留爷, 爷去投八路”的气概,只是觉得过不了就过不了,大不了从头再来.面试到最后, 我问面试官是哪个部门的, 回答说是"阿里云·云计算”部门,突然感觉今天被虐成渣不怨了, 心想如果这次面试通不过, 下次直接投云计算部门, 不投YunOS了, 后来跟同学说起这个想法,他说我是被虐疯了.
二面结束之后给磊哥发了一短信, 跟他说今天面试感觉不是太好.估计通不过了, 磊哥却说面试应该不会就此停下, 但是可能会中间再加一轮技术面, 由原来的三面变成四面. 原因是在我一面快结束时问了一下面试官对我的评价, 面试官除了说我真正的项目经验不足之外又说"大三能够有这样的扎实的基础已经相当不错了”, 褒奖之意溢于言表, 估计面试官给的评价应该不错, 因此如果二面面试官给个中评的话,那我就应该能够顺利的进入HR终面, 但如果是差评的话, 那就估计还要再加一轮技术面, 给出一个最终的技术评价.果不其然, 在等了一周之后, 三面来了...
三面:
在三面正式开始之前, 我先问了一句是技术面还是HR面, "是技术面”. 内心顿时紧张起来,但面试官告诉我不用紧张,放松就好,只是聊一下我这边的具体情况, 果然三面30多分钟基本上都是处于比较轻松的氛围之中. 问得问题有:我常用的数据结构有哪些, 对未来有什么打算, 对杭州有什么印象, 有没有女朋友, 有没有在杭州长期居住的打算,如果我去杭州的话, 我女朋友怎么办等等, 由于面试官很健谈, 后来又聊起了逻辑思维与追求完美的话题, 总的来说, 这一面并不如前两面那样技术氛围浓厚, 面试官也特别和蔼(由于面试官在正式面试之前曾经放过我鸽子, 面试开始时面试官竟然还不住给我道歉,真是受宠若惊了...), 后来面试官把他的两个联系方式都留给了我, 让我有什么就可以直接联系他, 后来在收到offer后联系团队时还跟面试官通过几次电话, 求面试官老师帮忙, 面试官老师在百忙之中还帮我联系HR , 告诉我该如何更快的融入团队.. 说实话, 真的非常感谢这位面试官.
四面:
四面是HR面, 万万没想到的是HR老师竟然在周天下午打电话过来, 当时刚刚打完羽毛球, 上气不接下气的接了HR的电话, 然后直接开始面试. 这次面试基本没问技术方面的问题, 由于我说了我的博客, 因此HR老师也看了一下我的博客, 见访问量还比较高, 我谦虚的说"可能是由于写的东西都比较基础, 因此看的人比较多吧O(∩_∩)O~~”; 然后又问到为什么不打算读研了; 在大学期间遇到的最大的困难是什么, 是怎么解决的; 除了上课,在大学里其他的时间都在干嘛等等. 总的来说, 这次面试虽然不涉及技术, 但大部分问题都是不太好答的, 因此, 在此建议大家在日常生活中对生活对一些思考, 不仅仅是为了应付HR, 更要活的明白一些.
四面结束之后, 自我感觉不错, 果不其然在第二周的周一, 收到offer通知, 知道自己的阿里面试算是可以告一段落了.
最后再说一下: 在每次面试快要结束时, 面试官都会让你问他/她一个或几个问题, 或者你自己主动问个问题, 在这儿我比较推荐的一个问题是"在您看来, 在阿里(当然是目标公司)如果要胜任一份工程师的工作, 他/她需要怎么样的能力或素质, 或者说如果我还想继续应聘这个工作, 我还需要做那些努力”, 这个问题暗含了三层意思:一是对我这次面试结果的询问, 二是我该如何努力弥补自己的不足,三是表达了你对这份工作的渴望,希望能够胜任或者获得这份工作. 我在四次面试中都主动或被动的问到了这个问题, 四面的面试官各自给出了自己的答案, 虽然答案各异, 但是综合起来能够得出一个对自己综合评价,同时,也能够知道为接下来迎接下一轮面试或者参加工作该做哪方面的努力, 因此我感觉这个问题还是比较好的.