谈到Linux C++服务端开发,无论Linux还是C++都是一个很大的话题。聪明的程序员需要学会做减法。
0. C++
简单谈一下C++。其实为了毕业找工作,熟练使用常用的C++语法就好了(C++11至少要知道一些基本的)。然后看基本C++的经典图书,学习一下安全编码、高效编码的规范(知乎上讨论C++的太多了,书我就不推了)。接着稍微研究一下C++底层原理就OK了。不要贪恋奇技淫巧,毕竟大学时间有限,语言只是一个解决问题的工具。我们还有更多高维的问题亟待解决。语言本身的高难知识日后慢慢学习就好了,很多时候书读百遍,不如实际工作中解决一个问题、实现一个需求提高的快。当然也有很多技术实际工作中用不到(或者说不让用)……
1. Linux
关于Linux,我想好好谈谈。大致分两块:一方面就是Linux的使用;另一方面就是Linux的环境编程。
1.1 Linux的使用
关于Linux,我想好好谈谈。大致分两块:一方面就是Linux的使用;另一方面就是Linux的环境编程。 1.1 Linux的使用 关于Linux的使用。就多使用就好了,从自己装系统开始,多折腾折腾。熟练了以后你不想折腾想稳定的话,可以买个云主机,在上面写写代码,让自己习惯终端,习惯命令行。各种命令眼花缭乱,靠背肯定是不行,一定要多用。书不需要通读,有一本随时能翻阅的工具书就够了。
日常使用Linux其实还是比较蛋疼的,毕竟没有Windows和Mac那么丰富的桌面软件。Ubuntu之类的我大学也经常玩,但不管是GNOME,KDE还是Ubuntu自家那个桌面都经常崩。其他兼容性问题也不少,直到有一次更新完,网卡驱动出问题连不上WiFi,以致于让我折腾了很长时间以后。我逐渐意识到自己脱离了本质。沉浸在解决这种不该解决的问题之中,还自得其乐。
后来我就用回了Windows(大学的时候没钱买MacBook),买了一个CentOS的云主机当自己的Linux学习环境(学生有优惠)。 Vim、Git的使用要熟练起来,在日后的工作中你离不开这两个工具。sed/awk也要学习一下,统计数据、定位问题的好帮手。其他各种零碎的小命令自然而然就会了(常见的用法经常忘可以记下来)。 此外呢,要学习Unix/Linux的一些基本概念、系统哲学。比如KISS、万物皆文件等等。不要觉得这些浪费时间,就当睡前读物或者厕所读物就好。这样更能激发你的学习兴趣,给你持久的学习动力。从Unix到Linux的发展历史,理清整个技术发展的脉络,了解那些光辉璀璨的人物和他们的英雄事迹。从里奇、汤普森,再到bill joy,从SMS到Linus。从开源运动的兴起到无处不在的Linux。这些故事不仅可以帮你产生学习的兴趣,也会让你学习到Unix/Linux背后的一些知识与设计哲学。 我推荐看一下这本《Unix & Linux大学教程》虽然名字像大学教材,其实是很经典的一本国外图书。当然你也可以先找本《鸟哥的Linux私房菜》来开开胃。
1.2 Linux系统环境编程
初学者可能会对Linux系统环境编程一词有误解。这好像是介绍如何在Linux系统上写代码?其实不是,这里指的是如何使用系统的API来编程。这些API都是C语言的,但和我们课本里的不太一样。我们通常学的C,都是ANSI C(IOS C)是国际统一标准的,不管Windows还是Linux都适用,但是每个操作系统都有其独有的系统级编程的API。Linux的系统API是来源于(兼容)Unix的。Unix的API在几十年的时间内,逐渐形成了标准:POSIX、SUS。POSIX和SUS的区别这里不谈了,大致可以认为我们要学习的Unix环境编程的API就是POSIX标准。
当然说都是POSIX也不尽然,在Unix的世界里,仍然有一些非标的东西存在。比如在SystemV和BSD分庭抗礼的时期,新生的API就出现过割裂的现象。举个例子,我们经常谈到IO多路复用,select其实是起源自System V的,而poll则出自BSD。很多后来的OS都不严格区分API的起源,默默兼容着两套API,比如Linux,直到后来Linux 2.6推出了自己更高效的API:epoll。当然BSD后面也推出了新的kqueue(这个Linux就不再支持了)。除此之外呢,指的一提的是,我们常说的三大IPC:消息队列、信号量、共享内存(当然IPC不止这几个)对应的API:
这些都是出自System V的。其实POSIX后来对这三大IPC也制定过自己的API标准,但是流行度就远远不如以上这几位老前辈了。这里看好像System V占了上风,但其实我们熟悉的socket那套API都是出自BSD,哈哈。
好了,一谈历史我就收不住,重新谈学习。我不建议一上来就找大部头阅读,从A刷到Z。我建议先随便去学校图书馆找一本薄薄的讲Linux C编程的书(尽量500页以内的),逐个章节建立起知识的框架。对系统编程有一个大体的认识。然后再去找一本大部头读一读。Stevens旷世三部曲其二的《APUE》《UNP》都是经典的图书。
《Linux编程接口》不知道为什么被翻译成了《Linux/Unix系统编程手册》,不过这不重要。《TLPI》行文风格,深入浅出。读起来更适合新手入门,作为长期的案边工具书也不错。我个人感觉是比《APUE》读起来更舒服的,而且也更加侧重Linux。另外这本书要比Stevens的那两本书年代要新,TLPI是2010年后出版,而Stevens 1999年就与世长辞啦,虽然其他人也给他的书修订过新版,不过我还是强烈推荐《TLPI》。
2. 道讲完了,再谈一下术
具体到服务端开发,其实主要就是学习各种IPC、socket、IO多路复用(或者说事件驱动)、pthread(多线程),当然socket也是一种IPC,只是它太特殊了,socket的知识复杂度是超过其他IPC方式的,故而单列出来。一言以蔽之,侧重点就是网络编程啦。从多进程到多线程,再到IO多路复用。学完基础,去学一学网络模型,了解reactor(反应堆)和proactor(前摄器)的区别,学一学半同步/半异步模型(或半同步/半反应堆)、领导者/追随者。blabla……
除了这些和C++语言之外就够了吗?不不不,还有TCP/IP和HTTP协议的知识了。甚至你需要简单学一下HTML、学一下JS。至少要知道前后端是如何交互的。
除了这些,以MySQL为代表的关系型数据库,以Redis为代表的内存KV数据库,还有MQ等等也是需要学习的。可以每一类找一个代表学一学。不一定要深入源码,因为组件层出不穷,学是学不完的,但至少要会用,知道如何使用这些组件去解决各种各样的实际问题(比如做个热门榜单,会想到Redis的zset)
另外很重要一点就是,大学期间对于专业课不要逃课。很多自学编程的同学们总是看不上大学老师那点东西,不去上课。在寝室里自学点Web框架之类的。我不反对学习,但是因为学这些就不去上专业课,真的是舍本逐末。框架本身只是一个经验性的东西,学的就是一个熟练度。培训机构的学生培训三个月玩的比你熟,人家还带项目……当然你也可以去深入研究一下框架的背后实现原理,但我希望你能明白我的意思:学习框架不能成为逃专业课的理由。不要觉得操作系统、计算机网络、数据结构、计算机组成原理这种东西假大空、不实际。错错错,莫莫莫。
一年半能作出什么?
其实你把网络编程弄熟,弄一个小的网络库或者RPC框架都是没问题的。或者自己实现一个简易的HTTP Server、FTP Server,或者小Redis(解析几个命令,实现内存存储)之类的。不需要做到工业级别,主要是把核心的想法实现,剩下的很多其实是重复性的工作,以及性能提升的工作。其实也不一定要自己做出来什么东西,我大学的时候也没做出来什么像样的东西(缺乏创意和耐心,我可能更喜欢命题作文啊……),但是我把环境编程玩的比较熟,还有就是计算机专业的基础打得比较好。后来大三的时候面试腾讯的暑期实习生,和面试官聊得很嗨皮。
慢慢来吧,不要想着一口气学完(不可能的)。『以有涯随无涯,殆已!』先建立知识框架,尽量每个知识领域都有涉及,然后逐步填充细节。大学期间不能眉毛胡子一把抓,要把Linux和C++学的比其他的更熟练,其他的对于大学生的掌握要求其实不高。随着工作的积累、经验的增长,很多知识其实会像倒排索引一样,慢慢填充到你的脑袋里,而不需要你对着目录从A到Z逐个学习。
如果你是在校学生,而且编程语言和数据结构的基础还不错,我认为应该在《操作系统》和《计算机体系结构》这两门课上下功夫,然后才去读编程方面的 APUE、UNP 等书。
学习操作系统的目的,不是让你去发明自己操作系统内核,打败 Linux;也不是成为内核开发人员;而是理解操作系统为用户态进程提供了怎样的运行环境,作为程序员应该如何才能充分利用好这个环境,哪些做法是有益的,哪些是做无用功,哪些则是帮倒忙。
学习计算机体系结构的目的,不是让你去设计自己的 CPU(新的 ISA 或微架构),打败 Intel 和 ARM;也不是参与到 CPU 设计团队,改进现有的微架构;而是明白现代的处理器的能力与特性(例如流水线、多发射、分支预测、乱序执行等等指令级并行手段,内存局部性与 cache,多处理器的内存模型、能见度、重排序等等),在编程的时候通过适当组织代码和数据来发挥 CPU 的效能,避免 pitfalls。Modern Microprocessors。