大家好。我先简单介绍一下自己,我是李鸿,目前负责马蜂窝内容中心的技术研发和团队管理。
接到今天这个任务的时候,我就在思考要分享什么内容。在座的同学应该有一些工作的时间比较久,也有一些刚从学校毕业。所以今天所讲的东西,如果能让不同阶段和技术背景的同学产生共鸣,让大家改变了一些对技术的看法,甚至是产生了一点对职业规划上的影响,我认为这次分享才有意思。
出于这些考虑,我选择了今天的主题——每个程序员都可以「懂」一点 Linux。
主讲人:李鸿
马蜂窝旅游网内容中心研发高级总监
李鸿,现为马蜂窝内容中心技术团队负责人。拥有十余年移动互联网从业经验,多年从事移动地图 App、LBS 企业级服务和智慧交通相关产品研发。个人技术兴趣聚焦在 Linux 生态,包括 Linux 内核等底层技术。
为什么讲这个主题?
想到这个内容,也是基于我自己在技术成长上的一些感悟。
我比在座大多数同学年长几岁,大概十几年前大学毕业。今天我在跟很多面试候选人聊的时候,我会问他们「为什么选择计算机专业」,大部分人给我的答案都是碰巧选了计算机,或者听说这个专业的就业前景不错。
当然也会有同学和我一样,是出于喜欢。我最早接触到计算机还是读初中的时候,当时电脑很贵,家里也没有。有一次在商店里我看到了一台「小霸王」学习机,有人通过在键盘上敲一敲,就能真的在屏幕上出现一点东西,我觉得简直太有意思了,就在当时,我知道自己以后一定会学计算机。
大学之后,基本大一大二接触的都是 Windows。一天偶然看到一些 Linux 代码,从那之后我就开始自学 Linux,直到钻研 Linux 的内核。十几年后我再来看,还是会感叹 Linux 世界的神奇,而且庆幸自己的选择没错。
所以今天,我想分享下在学 Linux 这个过程中的一些思考:什么才是真正的 Linux、它为什么好、我们应该从哪里入手开始学习,希望大家可以有所收获。
你 「懂」Linux 吗?
当问到是不是懂 Linux 的时候,包括我身边的很多朋友都会说「还可以啊,我一直都在用」;也可能会说「懂一点,我听说过 Linus 这个人」,等等。但至少我认为,如果你只是在说以下这些,真的不叫「懂」Linux:
那什么才叫「懂」Linux ?如果把这件事讲透,我认为核心要解决的就是三个「W」——What,Why,How。
What:一些同学在开始投入某个技术领域的时候,可能基础比较薄弱,会很辛苦地学习。学了一段时间以后自己觉得学到了好多东西,但其实很多人并没有学到这个方向的关键、核心和本质。比如我遇到过很多做大数据分析的人,说到 Hadoop、Spark,相关的单词可以说不少,但问到「Spark 和 Hadoop 有什么本质的区别」,「Spark 对数据的界定有什么本质的不一样」这些问题的时候,还是说不上来。
每个程序员的时间和精力是很宝贵的。在我们整个职业生涯中,可能用十年、二十年去学透一、两个东西已经很不容易了。如果决定花时间去学习某个技术之前,一定要想清楚学的是什么,千万不要学偏了,甚至都没走在自己规划的职业方向上。
Why:为什么学?是出于兴趣爱好?是对实施架构很重要?是会影响你的职业规划?是这项技术将来会有很好的市场收益?……不管你的答案是什么,自己要比较清晰。
有一些同学技术学得很杂,问哪个都说比较熟。但问他哪个技术他比较有研究,是他比较资深的,好像又都没有。这就是他没想清楚「Why」,也就想不清楚自己的重心要放在哪里。
How:前两个问题解决完,就应该去思考「How」。到底应该怎么学,才能学得越来越好。
今天我们是围绕 Linux 在解决这三个 W,换成任何别的技术,其实都有相通之处。最近 7、8 年我面试过不下 500 个 Java 研发,几乎每次我都会问「能不能用七八个概念说说你对 Java 的认识,或者你为什么喜欢 Java」,很少有候选人人能真的把这个问题说清楚。
所以我建议各位同学,以后再投入一项技术的学习之前,都先从以上三个 W 去审视一下,看你是不是真的清楚要学的是什么,为什么学,怎么才能学好。
What 什么叫做懂 Linux
1. 知道为什么学
一定不是说因为 Linux 「时髦」,也不是现在的工作中急需用它去解决某个问题,而是确实会对长远的知识架构和的职业发展产生质的影响,才值得花费精力和时间。
2. 知道要构建怎么样的 Linux 知识架构,并对专攻的技术方向提供源源不断的能量
学习一个东西要先看全局,要去想 Linux 整体的知识架构、各部分占的比重、在它背后还需要掌握哪些知识、学习它带来的收益是什么等等,真正形成系统和规范化的学习。如果一开始没有建立起整个知识架构的话,后面会浪费大量时间。
这里特别强调「专攻」。我认为专攻某个方向的价值远远大于泛泛地了解。大家职业生涯越是走得远,越会发现专攻某个方向的意义。如果开始就是泛泛地学,后面对自己的定位会非常困难,因为你不知道自己的优势是什么,适合在什么岗位,应该选择什么路径来发展。
3. 知道学习 Linux 的最优方法
要想学好 Linux,最核心的还是要找到正确的方法。什么才是学 Linux 最好的方法?是去翻翻文章、看看文档吗?是去学敲命令吗?是去学 SHELL 吗?如果这些都不叫「学」,什么才是学 Linux 最优的方法?
4. 知道 Linux 背后的设计哲学、优点、历史和文化
我们身边有很多技术同学关注的都是怎么使用 Linux ,于是就去把书里是怎么讲的、用过的人是怎么说的统统记下来,根本不会思考记录的这些内容背后体现了什么。如果长期只处在一个单向接收信息的过程里,你就无法练习出反思和总结的能力,更不要说可以达到批判性地审视某个技术,甚至提出质疑的水平。
而要想真正从学习中获得成长,能够和接收到的信息产生互动,去引发更多的思考,就要去知道 Linux 背后的设计哲学、它的优势、历史文化是什么。
5. 喜欢 Linux,爱上她
学习的辛苦、做研发的辛苦,相信大家都深有体会。那么坚持去学习、去学好某个技术的最大前提,是你要喜欢它,甚至热爱它。因为只有这样你才会觉得这个过程有意思,才会产生继续向下深挖的兴趣,才会愿意去做更多的推理。
不只是 Linux,包括现在工作中用的语言、开发环境等等,如果大家实在喜欢不起来,我建议你再去探索一下,去找到自己真正喜欢的领域。
说了这么多,如果用一个词来判断什么是「懂」Linux,我想应该是去看自己能不能真正「理解」Linux。
Why 为什么要懂Linux
今天的主题是「每个」研发都可以懂一点 Linux ,这是为什么?其实很多技术是可以不懂的。比对后端需要的是处理业务逻辑,那就不需要一定去懂前端的 WebGL;再比如做大数据的同学,也不需要太懂编译。为什么 Linux 我就建议每个同学都要去学一点?而且为什么在那么多操作系统中,我只挑了 Linux 呢?
为什么选 Linux ?
开放
投入一个有开放的心态、开放视角的技术,给我们带来的成长和收益将是无穷的,这也是开源世界带给我们的一个重要课题。我非常相信一点,随着国内经济的发展、大家认识的逐渐完整,中国的软件市场也会越来越开放,大家所处的大环境会越来越好。
Linux 的成功也一定离不开它的开放,离不开整个开源社区的贡献、生态的参与,以及由此带给大家的成就感,驱动他们更愿意去把一些成就分享出去,去开放合作,等等,这些都是促使 Linux 不断走向强大的原因。
遵循标准
对标准的遵循也是 Linux 可以达到今天这样成就的关键。这也是很大的话题。其中有一点我认为非常重要,就是它继承了 Unix 的设计思想,它的 Unix-alike (类 Unix 系统) 设计哲学。
因此,选择 Linux 就是因为它足够优秀,可以带给我们值得去探索和深思,并且可以运用到学习和工作中的知识和思想。
那学习操作系统的意义又是什么呢?
为什么要学操作系统
1. 带来视角上的提升和改变
简单画了一个图来代表我对计算机世界的一些理解,可以看到图中每个圆是一环套一环的:
(1)使用软件
最里面的圆代表的就是一个最小的视野,它对应的是用户拥有的视野。因为作为软件的使用人员,用户是不会去关心背后的开发原理、逻辑实现的,用户只关心这个软件是不是好用。
(2)开发软件
对于我们学计算机、做研发的人来说,去使用一个软件其实是比较容易的。因为我们所在的是「开发软件」这个圈子,相对于用户来说,我们站在一个更外围的视角,我们对使用软件这件事看得更加透彻,角度更开阔。
聊一个生活中的例子,我有一次去参观南京中山岭的宋美龄宫,在去之前听别人说,美龄宫像一颗宝石一样,被许多由不同颜色树叶构成的项链包裹在中间。听起来就很美,也我非常好奇,于是去了之后我一直在找这条「项链」。结果当然是找不到。因为大家所说的「项链」是通过航拍看到的图形,我是走在树林中,那肯定看不到。
俯拍
图:宋美龄宫
(来源于网络)
近景
你会发现,站的高度不一样,你的视角就会不一样。同样的道理,研发同学之所以理解和使用软件更快,就是因为与用户相比站的角度更高,看的范围更广,我们知道软件设计背后的原理,以及它的交互逻辑,就会很快上手。
(3)开发框架和库
如果大家去听一个前端的讲座,为什么当介绍到讲师是某个框架的作者时,我们就会觉得这个分享很厉害?
绝大部分研发,可能 80%~90% 甚至 95% 的同学都是处在「开发软件」这个层面的,我们使用各种现存的框架、开发库去实现业务逻辑。
但是一定有少部分研发关注的是更外围的事情,去做一些开发框架、开发库的实现。这一层的研发需要的能力确实要更强,因为他要思考整个框架怎么拆分模块,怎么样去适应接口让程序员用更好地用起来等等,所以要考虑得更深、更广,挑战也更多。
细心的同学可能注意到了我在「开发软件」与「开发框架和库」中间画了一条红线。我想表达什么意思是,软件研发同学会做出一些很棒的软件,是因为你有这样的能力,也是因为大家头上是戴上了一顶那些开发框架和库的同学给的安全帽的。比如 Java 开发会考虑内存的管理和回收,但这个机制其实是做 Java 开发环境的人帮你做了考虑,帮你提供了应对问题的策略,可以让你更「安全」地做事情。
(4)操作系统
再往下看,所有的开发库和开发框架,都是放在一个操作系统上的,与之对应的这一层的研发人员考虑的东西会更加复杂,因为他们要提供的是最基础的环境,是上层实现的基石。
(5)硬件、规范、协议
大家看到再往下我画了一个骷髅,也就是说这一层是真正厉害的人,他们做的是硬件、规范和协议,比如说指令系统,我们说的复杂指令系统和简洁指令系统这两个大的指令系统的阵营,在二三十年的时间里都一直在为自己的阵营 PK,目的是为了讨论出更适合软件发展的规范。再比如发明 TCP/IP 协议的人,他们最初在一片混沌的状态下,居然能够提出 TCP/IP 的概念,让我们现在可以非常简单地去做通讯。所以达到这一层的人,我们已经称为天才了。
(6)数学
再往下就是数学。我认为计算机回到最后一定是数学,比如说在大学我们都要学习的离散数学、统计学、范式、逻辑学、图灵机等等。数学是对整个计算机体系提升一个最基础的支撑。
所以通过这个图形我们还可以看到,研发同学如果要持续地成长,是绝对存在路径的。我觉得有两个角度是大家可以思考,一是你在专注的方向持续地积累,形成自己的竞争壁垒;同时你可以尝试走入下一个更大的层面,看一看是不是会你的视野,对服务的一些思考,对解决问题的能力都带来一些帮助。
搞技术做工程,如果思想越高、越宏观、越系统,能达到的能力就会越强。懂一点 Linux,首先就是为我们提供这样一种提升视角的方法,帮我们站在一个更外围的角度思考每天的工作和专攻的技术,它们背后是什么样的实现原理和设计思想,它处在怎样的一个体系中,获得了怎样的支撑。
2. 构建高效的工作和学习环境
学习 Linux 另外一个非常有用的地方就是「效率」的提升。研发同学每天都要和操作系统打交道,在上面做大量的工作和学习,不管是写代码、看文档、自动跑一些任务、做一些搜索、写一些东西等等。如果懂一点 Linux,懂它的设计哲学,你能更好掌握怎么去用 Linux 更高效。
不夸张地说,如果你真的能够成为一个 Linux 的 Hacker,我认为的你的工作和学习效率提升十倍以上是没问题的。我自己就会用 VIM 的话来解决几乎所有问题。
计算机一个最本质的地方就是「自动化」,所以大家要真的能够理解「自动化」这个词的意义。我们写软件、做管理系统,都是为了要解决以前需要人工来做的事,更好地解放我们的大脑。
既然自动化是最本质的,我们就应该反思在自己的工作和学习中,是不是用到了自动化的思想,你是不是还可以忍受机械、繁琐、低效地处理问题?现在的方式是不是应该改进?通过去学 Linux,可以帮助我们构建一个高效的学习和工作环境,去解决这些问题。
3. 借鉴优秀的学习样板和实例
第三个就是对 Linux 的借鉴。其实所有的计算机工程问题,无非都是围绕架构设计、技术选型、代码质量、设计风格、工作流程,自动化程度等相关的问题。如果可以做到理解 Linux,你就会发现在这个操作系统上的很多组件,其实就为我们提供了如何解决计算机工程问题非常多有益的实例。
就如大家在关注一些优秀的开源项目的讨论列表时,你也会觉得有一些人提出的建议并不好,但你可能说不清原因。这时有人做出了一些列举,论证这个建议为什么不好,你就会非常认同,并且吸取他思考问题和解决问题的方法。学习操作系统的过程也一样,Linux 本身就是一个很好的样板和实例,包括它的设计理念、代码质量、文档编写、协同、软件工程、演进以及它的文化,方方面面都会为我们提升非常好的借鉴。
这里我想再展开说一下演进和文化。
演进是什么?其实我们很多人在做项目的时候是很容易走偏的,因为计算机世界每增加一个维度,它可选择的结果都会带来级数级别的增长。而我们在一个软件项目的推进实现中,要考虑的维度可能成百上千。要在这些纷繁复杂的选择中真的找准方向去演进,需要非常清晰地思考。通过去看一个软件的发展历史,你可以去体会那些优秀的人是如何在一些关键的点上把握方向,来为你自己在做判断的时候提供指导。
另外就是文化。我认为包括 Linux 在内的开源项目,核心的文化就是「就事论事,有技术情怀,追求极致,Open 的沟通」。这些理念对每个技术人员的成长都非常重要。比如当我们身处一个规模比较大的公司,成员之间难免会存在沟通上的障碍,可能就会导致误解的产生和对对方的不认可。如果大家以一个统一的文化作为前提,就会用彼此认同的理念和方式去思考问题,也就更容易达成协作。
How 怎么做到懂 Linux
最后我们看看用什么方法去学习,才能够越来越懂 Linux。
1. 理解设计哲学
我们只有对一件事有了深刻的认识,并且认同之后,才有可能去花时间学好。所以首先我认为要深刻认识到 Linux 背后的设计哲学是什么。
关于 Linux 的设计哲学很多地方都有介绍,我这里也特意没有进行翻译,希望大家对表述中关键的英文单词也建立起认知:
下面我把每个点简单地说一下。
"Everything is a process; if it's not a process, it's a file"
Linux 操作系统认为「任何事都是一个进程,或者说一个线程,是一个执行体;如果它不是一个线程,那么它就是一个文件。」
大家不要认为这句话理所当然,其实很多操作系统都没有这样一个概念,但是在 Linux 的世界,大量的东西是以进程的概念存在的。如果你认为它不是一个可以运行的东西,那它极大可能就是个文件。你会发现很多新的技术都是在这样的设计思想之上,比如说容器。
这种思想的好处是什么呢?我们说解决计算机的问题有一个重要的技巧,就是当你能够把各种复杂的事情都看成是一码事儿,能够从统一的视角去概括它,并且面对它、处理它,那解决起来就会容易很多。因为当计算机面对复杂的现实世界,它能做的就是一层一层的抽象,最后抽出一个非常简单且统一的视角,可以直接地去处理。这是大家在写代码的时候可以去思考的。当你发现你做出的设计能够把两、三个不一样的东西,从一个更高的视角进行统一,这时的你就会比很多人了不起。
"One tool to do one task"
第二点,一个工具解决一个问题。它的理念是说要把东西做好、做到极致,就要去做专。如果你做的不能比别人更好,你就不要去做,而是要去想如何通过一种方式让用户可以在你的应用上调用自己喜欢的东西,这就是 One tool to do one task。对我们在做程序的时候也有很多帮助,比如是不是能把现在的应用做得非常内聚,而不是去做更多的东西。
"Three standards I/O channel"
第三点是说每个进程都有三个标准的 I/O:标准输入、标准输出、标准错误,好处是你就会清楚地知道任何终端进程默认都有这三个数据交流的端口,可以自由的进行拼装或者 I/O 重定向,进行功能组合,这其实也就是第四个哲学所说的——
"Combine tools seamlessly"
把工具无缝地拼接起来。
"Plain text preferred"
这一点也是我非常喜欢的,就是能用 Text 一定要用 Text。Text 是一种人可以读,机器也可以处理的内容,可以解决好多问题。我们一般说 Plain Text 是指英文。比如说大家写注释要用英文写,它带来的好处是,我们可以通过脚本自动化分析各种 Comment,谁的 Comment 写得多,谁的单词拼错了,谁的 Comment 中包含非常重要的信息,需要重点去跟踪等等。
"CLI, not GUI"
提倡用命令行,不要用图形化界面。因为命令行可以非常高效进行人机对话,图形化界面对程序员来说是非常低效的。如果做一次更改,我们更希望通过敲键盘的方式来快速告诉计算机应该做什么。
"Provide the mechanism, not the policy"
这点我建议大家背下来,就是如果你做一个好的大型框架,应该去提供机制,而不是提供策略。也就是要提供创造更多可能性的能力,不要把需要适应到特殊场景下的定制化的内容写死在代码里。所有的软件在这种设计上这点是非常相通的,好的软件一定是为大家提供更多的灵活性和适用场景。
2. 学习 Linux 的三个层次
以上的设计哲学都非常重要。那么知道了这些,该怎么学 Linux 呢?大家不要在一开始学的时候就一定要去学内核,或者想要全都懂,于是就认为 Linux 很难。关于「懂」Linux 的阶段,我简单分成了三个层次:
第一个层次就是 Use,先用起来。但前提是用的时候要符合上面提到的那些标准,也就是要了解它的设计哲学,要知道它的优势,而不是只听别人说怎么配、怎么选才好。
如果把懂 Linux 分为十个「档」,那么 Use 对应的大概是 1-3。其实对于我们 70-80% 的程序员来说,到这里已经非常不错。
第二个层次是 Code。这里的 Code 不是指在后台写一个 Java 的业务程序,或者是前台写一个网页,而是指系统编程(System Programm),通过编码的方式和操作系统直接对话,而不再是点击鼠标去控制。
虽然系统编程跟大部分人的工作不会强相关。但是通过在应用层用语言(主要是 C 语言)去跟操作系统对话,你会看到在整个操作系统背后的一系列东西是怎么构建起来的,去我们提高视野、提升效率,以及得到更多优秀的借鉴都有很多帮助。除了 Code,如果大家有时间和精力,我建议还可以去了解一下 C 语言。C 语言非常纯粹,就是来告诉你内存长什么样,怎么去控制内存、指令、堆栈,怎么去进行参数传递的方法调用等,你会学到大量计算机架构相关的原理。
第三层是 Hack,它的档到对应到 8-10, 这可能是每个希望做到极致的技术人最后的追求,去了解内核这一层。
第一阶段:Use Linux
(1)终端、键盘、命令。刚才在讲 Linux 的设计哲学时,我们提到过一条——「CLI, not GUI」。所以对于程序员来说,在学如何跟 Linux 操作系统对话的时候,一定是使用终端、键盘、命令。我想跟大家说,如果你现在还习惯用鼠标,那你可能要反省,看看自己对自动化理解的程度是不是太低了。
(2)一个字符编辑器。要去找一款自己喜欢的字符编辑器,并且用起来。
(3)SHELL。第三,如果要用 Linux 理论去提高我们的视角,就一定要掌握一版 SHELL 脚本,并且去深刻理解。至于用哪个版本大家可以根据自己的喜好决定,目前我用的是 ZSH,感兴趣的同学可以去了解下。
(4)文件系统、进程线程、IO 组合、用户权限、资源管理。再往下我们可以尝试通过编程的方式去调用文件系统、进程线程、IO、用户权限、资源管理等等,去更加系统的了解。这些都会了之后会发现慢慢,以后再写一种高层的代码也就没那么难了。
(5)解剖 Linux。通过解剖 Linux 可以知道 Linux 是怎么装拼起来的,对它会有一个更直观的认知。我大概在十年前开始接触 LFS(Linux From Scratch LFS),现在它已经演化出了无数个版本,它会告诉你如何开始从零构建一个 Linux 系统,而且它好的地方在于是从源代码的方式去讲怎么编译,最后拼成一个操作系统。这个工作因为需要比较多的精力,所以建议大家三个月到半年的时间跑一次,会很有成就感。
(6)深刻理解背后的文化和哲学。关于 Linux 背后的文化和哲学,可能总结起来就是那么简单几句话,开始会比较难理解。但是大家如果把这几句话当成一种「信仰」,每次在学和用的时候都能再深刻地体会一遍,可能过了半年,说不定某一天你会突然发现想通了。
(7)参与社区。大家在参与社区的时候,一定要知道知识的价值是要通过 10 年、20 年的努力去沉淀、去积累的,要持续地参与到社区当中。
(9)最后一个就是持之以恒,去融入到你的工作、学习和生活当中。Linux 学习曲线的特点是一开始就很陡,不像 Windows,一开始很平滑。但一旦爬过这个陡坡,就会看到一个全新的世界,并且可以一直持续往上走。
第二阶段:Code Linux
这个阶段就是刚才我们讲到的,要用编程语言去和 Linux 对话,通过 Code 开始了解二进制 ELF。ELF 是在 Linux 世界的执行文件格式,通过了解 ELF 可以知道一个执行文件是怎么拼写的,它的内存是怎么存在的,指令是怎么跑的,数据是怎么取的,动态库是怎么加载的……如果把这些都搞定,至少在 Linux 领域,就不会再有什么是让你觉得理解起来比较吃力的事情。
第三阶段:Hack Linux
关于如何 Hack,这个问题非常庞大和复杂。如果大家有尝试走到这一层的勇气和愿望,我非常愿意和大家一起交流。
总结
总结一下今天我们讲到的一些内容:
- 知道为为什么要学 Linux:视野、效率、借鉴
- 知道要构建什么样的 Linux 知识架构,并对自己专攻的技术方向提供源源不断的能源:三个 W(What, Why , How)
- 知道学习 Linux 最优方法:确定层次 (Use, Code, Hack),实践,持之以恒,融入每天的工作、学习和生活
- 知道 Linux 背后的设计哲学、优点、历史和文化
- 喜欢上 Linux,爱上她
在分享最后,我想和大家聊聊最近经常思考的一个问题。现在我们总会听到身边一些人在抱怨,说计算机行业已经非常饱和,互联网也已经发展到了一定阶段,再过五年十年计算机就要被淘汰了,研发人员也会面临失业。
我对这个观点是非常不赞同的。
每个人都可以不用工作,每天很开心地享受生活,这应该是大多数人理想的状态。但是人类总要养活自己,唯一能达到这种理想状态的情况,就是由计算机、机器人、电脑帮我们人类完成大部分的工作,不管是做家务、交通出行、盖房子等等。如果这个理想状态的标准是 100 分,对比我们现在,可能仅仅处在 0.1 分的阶段。所以怎么可能会存在纯粹的失业呢?
为什么大家还要进行这样一个讨论?我只能认为有些程序员还没有喜欢计算机,担心自己学不好。学习这个过程的确不容易。就像我们看一本哲学书,开始想要读懂非常困难,但随着人生阅历的增长,随着我们在生活、学习和工作中不断验证书中的道理,你就会体会到其中的道理,提升自己看问题的视角和解决问题的能力。所以最后,我希望大家不要害怕学习,并且相信这个行业的前景,和程序员这份职业可以创造的价值。
以上就是我的分享,谢谢!