learn-tech/专栏/左耳听风/075程序员练级攻略(2018):系统知识.md
2024-10-16 06:37:41 +08:00

140 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

因收到Google相关通知网站将会择期关闭。相关通知内容
075 程序员练级攻略2018系统知识
进入专业的编程领域,学习系统知识是非常关键的一部分。
首先推荐的是翻译版图书《深入理解计算机系统》原书名为《Computer Systems A Programmers Perspective》。不过这本书叫做《程序员所需要了解的计算机知识》更为合适。
本书的最大优点是为程序员描述计算机系统的实现细节,帮助其在大脑中构造一个层次型的计算机系统。从最底层的数据在内存中的表示到流水线指令的构成,到虚拟存储器,到编译系统,到动态加载库,到最后的用户态应用。通过掌握程序是如何映射到系统上,以及程序是如何执行的,你能够更好地理解程序的行为为什么是这样的,以及效率低下是如何造成的。
再强调一下,这本书是程序员必读的一本书!
然后就是美国计算机科学家 理查德·史蒂文斯Richard Stevens 的三套巨经典无比的书。(理查德·史蒂文斯于 1999 年 9 月 1 日离世,终年 48 岁。死因不详,有人说是滑雪意外,有人说是攀岩意外,有人说是滑翔机意外。总之,家人没有透露。大师的 个人主页 今天还可以访问。)
《Unix 高级环境编程》。
《Unix 网络编程》 第 1 卷 套接口 API 、第 2 卷 进程间通信 。
《TCP/IP 详解 卷 I 协议》。
这几书的地位我就不多说了,你可以自己看相关的书评。但是,这三本书可能都不容易读,一方面是比较厚,另一方面是知识的密度太大了,所以,读起来有点枯燥和乏味。但是,这没办法,你得忍住。
这里要重点说一下《TCP/IP 详解》这本书,是一本很奇怪的书。这本书迄今至少被 近五百篇学术论文引用过 。这本写给工程师看的书居然被各种学院派的论文来引用,也是很神奇的一件事了。而且,虽然理查德·史蒂文斯不是 TCP 的发明人,但是这本书中把这个协议深入浅出地讲出来,还画了几百张时序图,也是令人叹为观止了。
如果你觉得上面这几本经典书比较难啃,你可以试试下面这些通俗易懂的(当然,如果读得懂上面那三本的,下面的这些也就不需要读了)。
《Linux C 编程一站式学习》。
《TCP/IP 网络编程》。
《图解 TCP/IP》这本书其实并不是只讲了 TCP/IP应该是叫《计算机网络》才对主要是给想快速入门的人看的。
《The TCP/IP Guide》这本书在豆瓣上的评分 9.2,这里给的链接是这本书的 HTML 英文免费版的,里面的图画得很精彩。
另外学习网络协议不单只是看书你最好用个抓包工具看看这些网络包是什么样的。所以这里推荐一本书《Wireshark 数据包分析实战》。在这本书中,作者结合一些简单易懂的实际网络案例,图文并茂地演示使用 Wireshark 进行数据包分析的技术方法,可以让我们更好地了解和学习网络协议。当然,也拥有了一定的黑客的技能。
看完《Unix 高级环境编程》后你可以趁热打铁看看《Linux/Unix 系统编程手册》或是罗伯特·拉姆Robert Love的 Linux System Programming 英文电子版 。其中文翻译版Linux 系统编程 也值得一读虽然和《Unix 高级环境编程》很像,不过其主要突出的是 Linux 的一些关键技术和相关的系统调用。
关于 TCP 的东西,你还可以看看下面这一系列的文章。
Lets code a TCP/IP stack, 1: Ethernet & ARP
Lets code a TCP/IP stack, 2: IPv4 & ICMPv4
Lets code a TCP/IP stack, 3: TCP Basics & Handshake
Lets code a TCP/IP stack, 4: TCP Data Flow & Socket API
Lets code a TCP/IP stack, 5: TCP Retransmission
对于系统知识,我认为主要有以下一些学习要点。
用这些系统知识操作一下文件系统,实现一个可以拷贝目录树的小程序。
用 fork / wait / waitpid 写一个多进程的程序,用 pthread 写一个多线程带同步或互斥的程序。比如,多进程购票的程序。
用 signal / kill / raise / alarm / pause / sigprocmask 实现一个多进程间的信号量通信的程序。
学会使用 gcc 和 gdb 来编程和调试程序(参看我的《用 gdb 调试程序》一、二、三、四、五、六、七)。
学会使用 makefile 来编译程序(参看我的《跟我一起写 makefile》一、二、三、四、五、六、七、八、九、十、十一、十二、十三、十四
Socket 的进程间通信。用 C 语言写一个 1 对 1 的聊天小程序,或是一个简单的 HTTP 服务器。
C10K 问题
然后当你读完《Unix 网络编程》后,千万要去读一下 “C10K Problem 中文翻译版”。提出这个问题的人叫丹·凯格尔Dan Kegel目前工作在美国 Google 公司。
他从 1978 年起开始接触计算机编程,是 Winetricks 的作者,也是 Wine 1.0 的管理员,同时也是 Crosstool 一个让 gcc/glibc 编译器更易用的工具套件)的作者。还是 Java JSR 51 规范的提交者并参与编写了 Java 平台的 NIO 和文件锁,同时参与了 RFC 5128 标准中有关 NAT 穿越P2P 打洞)技术的描述和定义。
C10K 问题本质上是操作系统处理大并发请求的问题。对于 Web 时代的操作系统而言,对于客户端过来的大量的并发请求,需要创建相应的服务进程或线程。这些进程或线程多了,导致数据拷贝频繁(缓存 I/O、内核将数据拷贝到用户进程空间、阻塞 进程 / 线程上下文切换消耗大,从而导致资源被耗尽而崩溃。这就是 C10K 问题的本质。
了解这个问题,并了解操作系统是如何通过多路复用的技术来解决这个问题的,有助于你了解各种 I/O 和异步模型,这对于你未来的编程和架构能力是相当重要的。
另外,现在,整个世界都在解决 C10M 问题,推荐看看 The Secret To 10 Million Concurrent Connections -The Kernel Is The Problem, Not The Solution 一文。
实践项目
我们已经学习完了编程语言、理论学科和系统知识三部分内容,下面就来做几个实践项目,小试牛刀一下。实现语言可以用 C、C++ 或 Java。
实现一个 telnet 版本的聊天服务器,主要有以下需求。
每个客户端可以用使用telnet ip:port的方式连接到服务器上。
新连接需要用用户名和密码登录,如果没有,则需要注册一个。
然后可以选择一个聊天室加入聊天。
管理员有权创建或删除聊天室,普通人员只有加入、退出、查询聊天室的权力。
聊天室需要有人数限制,每个人发出来的话,其它所有的人都要能看得到。
实现一个简单的 HTTP 服务器,主要有以下需求。
解释浏览器传来的 HTTP 协议,只需要处理 URL path。
然后把所代理的目录列出来。
在浏览器上可以浏览目录里的文件和下级目录。
如果点击文件则把文件打开传给浏览器浏览器能够自动显示图片、PDF或 HTML、CSS、JavaScript 以及文本文件)。
如果点击子目录,则进入到子目录中,并把子目录中的文件列出来。
实现一个生产者 / 消费者消息队列服务,主要有以下需求。
消息队列采用一个 Ring-buffer 的数据结构。
可以有多个 topic 供生产者写入消息及消费者取出消息。
需要支持多个生产者并发写。
需要支持多个消费者消费消息(只要有一个消费者成功处理消息就可以删除消息)。
消息队列要做到不丢数据(要把消息持久化下来)。
能做到性能很高。
小结
到今天,我们已经学习完了专业编程方面最为重要的三部分内容:编程语言、理论学科和系统知识,我们针对这些内容做个小结。如果想看完我推荐的那些书和知识,并能理解和掌握,我估计怎么也得需要 4-5 年的时间。嗯,是的,就是一个计算机科学系科班出身的程序员需要学习的一些东西。这其中,最重要的是下面这几点。
编程语言。以工业级的 C、C++、Java 这三门语言为主,这三门语言才是真正算得上工业级的编程语言,因为有工业级的标准化组织在控制着这几门语言,而且也有工业级的企业应用。尤其是 Java还衍生出了大量的企业级架构上的开源生态。你至少需要掌握 C 语言和 Java 语言,这对你以后面对各式各样的编程语言是非常重要的。
此外,还推荐学习 Go 语言,它已成为云计算领域事实上的标准语言,尤其是在 Docker、Kubernetes 等项目中。而且Go 语言在国内外一些知名公司中有了一定的应用和实践,并且其生态圈也越来越好。
算法和数据结构。这个太重要了,尤其是最基础的算法和数据结构,这是任何一个称职的程序员都需要学习和掌握的。你必需要掌握。
计算机的相关系统。你至少要掌握三个系统的基础知识,一个是操作系统,一个是网络系统,还有一个是数据库系统。它们分别代表着计算机基础构架的三大件——计算、存储、网络。
如果你能够走到这里,把前面的那些知识都了解了(不用精通,因为精通是需要时间和实践来慢慢锤炼出来的,所以,你也不用着急),那么你已经是一个非常非常合格的程序员了,而且你的潜力和可能性是非常非常高的。
如果经历过这些比较枯燥的理论知识,而且你还能有热情和成就感,那么我要恭喜你了。因为你已经超过了绝大多数人,而且还是排在上游的比较抢手的程序员了。我相信你至少可以找到年薪 50 万以上的工作了。
但是,你还需要很多的经验或是一些实践,以及一些大系统大项目的实际动手的经验。没关系,我们后面会有教你怎么实操的方法和攻略。
但是,往后面走,你需要开始需要术业有专攻了。下面给一些建议的方向。
底层方向:操作系统、文件系统、数据库、网络……
架构方向分布式系统架构、微服务、DevOps、Cloud Native……
数据方向:大数据、机器学习、人工智能……
前端方向:你对用户体验或是交互更感兴趣,那么你走前端的路吧。
其它方向:比如,安全开发、运维开发、嵌入式开发……
这些方向你要仔细选择,因为一旦选好,就要勇往直前地走下去,当然,你要回头转别的方向也没什么问题,因为你有前面的这些基础知识在身,所以,不用害怕。只是不同的方向上会有不同的经验积累,经验积累是看书看不来的,这个是转方向的成本。