本书从操作系统原理角度讲解进行C++服务器开发所需掌握的技术栈。全书总计9章,第1~2章讲解C++ 11/14/17新标准中的常用特性、新增类库,以及C++开发者必须熟练掌握的开发调试工具链;第3~6章详细讲解C++服务器开发中的多线程编程技术、网络编程重难点知识、网络故障调试与排查常用工具,以及通信协议的设计思路、技巧;第7~8章详细讲解一个带网络通信组件的高性能服务的基本设计思路和注意事项;第9章进一步补充服务相关的常用模块设计思路和方法。本书秉承的思想是,通过掌握技术原理,可以轻松制造“轮子”,灵活设计出优雅、鲁棒的服务,并快速学习新技术。
无论是对于C/C++开发者、计算机专业的学生,还是对于想了解操作系统原理的读者,本书都极具参考价值。
从原理角度讲解C++服务器开发技术栈,内容详尽细致、版本新,非常棒的C++服务器开发参考书
张远龙,微信公众号“高性能服务器开发”的作者,曾就职于银天下、携程、字节跳动等公司,做过金融交易系统、IM、呼叫中心等项目,研究方向为高性能高并发服务开发。
为什么写作本书
笔者自学生时代便开始接触 C++,工作以后先后负责过 C++客户端和服务端的开发工作。时至今日,C++仍然是笔者最喜欢的编程语言。在笔者看来,C++一旦学成,奇妙无穷,还可以快速学习其他编程语言和技术。
本书讲解了笔者近十年来使用 C++的一些经验和技巧,着重讲解基于 C++的操作系统原理和服务器开发技术,希望读者通过学习本书,可以了解如何学习 C++,以及如何成为一名合格的C++开发者。
C/C++的当前应用领域
需要注意的是,本书不细分C语言与C++的区别。在通常情况下,我们可以将C++看作C语言的一个超集。C++虽然从功能层面来看,离C语言越来越“远”,但从语法层面来看,其大多数语法与C语言基本一致。对于C++面向对象的特性,如果仔细探究的话,我们会发现C++类方法的具体语法还是C语言的过程式语法,虽然这种现状正在不断改变。
C语言目前主要用于操作系统类偏底层的应用开发,比如Windows、Linux这样的大型商业操作系统,以及嵌入式操作系统、嵌入式设备。有些开源软件也会选择C语言进行开发,主要是考虑程序执行效率和生成的可执行文件的体积(C代码生成的可执行文件体积相对较小),当然,其中不乏一些历史技术选型的原因,比如Redis、libevent、Nginx等。
在将高级语言翻译成机器二进制码时,C++编译器生成了大量的额外机器码,而这种机器码相对于C语言来说不是必需的。例如,对于一个C++类的实例方法,编译器在生成这个方法的机器码时,会将函数的第1个参数设置为对象的this指针地址,以此来实现对象与函数的绑定。正因如此,许多开发者都会优化和调整编译器生成的汇编代码。
C++当前的常见应用领域有:①我们目前见到的各种桌面应用软件,尤其是Windows桌面软件,例如QQ、安全类杀毒类软件、浏览器等;②一些基础软件和高级语言的运行时环境,例如大型数据库软件、Java虚拟机、C#的CLR、Python编译器和运行时环境等;③业务型应用软件的后台,例如大型网络游戏的服务端和一些企业内部的应用系统等。
C++与操作系统
虽然Java、Python等的SDK或运行时环境最终也会调用操作系统API,但其自带的SDK或者运行时环境都提供了常见的操作系统功能。而C++的运行时环境一般是操作系统自身,因此C++是离操作系统更近的一种编程语言,执行效率更高。
但是,C++的整套语法不具备“功能完备性”,在大多数情况下,单纯地使用其本身提供的功能无法创建出任何有意义的程序,还必须借助操作系统API来实现。例如,C++本身不直接提供网络通信功能的SDK,必须借助操作系统提供的套接字API才能实现网络通信;而对于Java来说,JDK自带的java.net、java.io等包则提供了完整的网络通信功能。所以,熟悉操作系统相关原理和API是用好C++的前提,这也是C++难学、对新手不友好的主要原因之一。
不过,随着C++标准和版本的不断迭代,这种现状正在改变:在C++标准库中引入了越来越多的功能,避免直接调用操作系统API。
不管怎样,应用直接使用操作系统API,程序执行效率高,控制力度大,开发能力仅仅限制于操作系统本身,这是 C++的优势之一。比如对于 Java,假设操作系统提供了某个功能,但Java虚拟机不提供该功能,则开发人员也无法使用该功能。
编程大师Charles Petzold曾说过,操作系统是一个非常复杂的系统,在API之上加一层编程语言并不能消除其复杂性,最多将复杂性隐藏起来而已,而懂得系统API能让我们更快地挣脱困境。
如何看待C++ 11/14/17/20标准
C++既支持面向对象设计(OOP),也支持以模板语法为代表的泛型编程(GP)。从最初业界和开发者翘首以盼的C++ 11标准开始,历经C++ 14、C++ 17,到今天的C++ 20,版本差别越来越大,原来需要使用的第三库的功能也被陆续添加到C++标准库中。C++标准不断发展,遵循C++最新标准的编译器层出不穷,C++变化越来越大、越来越快。
对于C++ 11、C++ 14、C++ 17乃至C++ 20的学习,笔者建议以实用为主,不必太纠结新标准中的一些高级特性和复杂模板,更应该学习其中实用的语法和工具库。
如何学好C++和后端开发
首先,我们应该打好基础。我们要熟练使用C++,还要结合具体的操作系统学习C++,熟悉某操作系统的API函数,以及与系统API关联的各类技术,比如各种进程与线程函数、多线程资源同步函数、文件操作函数、系统时间函数、内存分配与管理函数、网络编程、PE或ELF文件的编译、链接原理等。
如果已打好基础,就可以找一些高质量的开源项目去实战。最好找一些没有复杂业务的开源项目,或者是自己熟悉其业务的开源项目(如IM系统)。如果不熟悉其业务,那么不但要学习其业务(软件功能),还要学习其源码,最终两者难以兼顾。
因此,在学习这些项目之前,应该先确定自己的学习目的。如果学习目的是学习和借鉴这款软件的架构设计,那么建议先进行整体把握,不要一开始就迷失在细枝末节中,这叫作“粗读”。如果学习目的是学习开源软件在一些细节上的处理方法,那么可以有针对性地阅读自己感兴趣的模块,深入每一行代码。当然,学习适合自己当前阶段的项目源码才是最好的。
学习的过程一般是接触、熟悉、模仿、创造。不管对什么开源项目,在没有任何思路或者解决方案时,我们都应该先接触、熟悉、不断模仿,做到至少心中有一套对某场景的解决方案,再来谈创新、批判及改造。
笔者在学习陌生的开源项目时,喜欢先将程序用调试器正常“跑”起来;然后中断,统计当前的线程数,通过main函数从主线程追踪其他工作线程是如何创建的;接着分析和研究各线程的用途和线程之间的交互,这样可以做到整体性把握;最后找感兴趣的细节去学习。
总之,C++是一门讲究深度的编程语言,其“深度”不体现在掌握多少C++语法,而在于是否熟悉所写的C++代码背后的系统原理,这是需要长期积累的,当然,一旦学成,就可以快速学习其他编程语言和框架。
本书概要
本书总计9章,主要基于C++,详细讲解服务器开发中基础且重要的技术栈,以期读者掌握“造轮子”的方法。
第1章讲解C++新标准中新增的常用语言特性和类库。
第2章讲解C++开发者应该掌握的各类开发工具和工作环境,详细、深入地讲解Linux gdb调试方面的内容。毫不夸张地说,掌握了gdb调试,就等于拿到了学习各种C++开源项目的“钥匙”。
第3章详细讲解多线程的原理,涵盖Windows和Linux的各类线程同步原语,以及基于线程同步技术、生产者/消费者模型衍生的队列系统。
第4章进行操作系统层面的网络编程重难点解析,讲解Linux上的常用网络通信模型,通过大量详尽的代码实例和测试,深入浅出地探究和验证网络通信编程的重难点技术。
第5章讲解排查和定位网络通信问题的常用开发工具。
第6章详细讲解网络通信协议的设计思想,并从“造轮子”的角度讲解常用网络通信协议的格式、使用方法和注意事项,讲解设计网络通信协议时需要考虑的各类问题,最后对几种常用的通信协议逐一剖析并给出具体的实现逻辑。
第7章详细讲解如何设计一个高性能的带网络通信组件的服务,并结合一些经典案例进行分析,还详细讲解经典服务框架的设计思路和各个模块的具体实现方法。
第8章以redis-server源码为例,论证第7章讲解的服务设计原理。
第9章是对第7章内容的补充,详细讲解一个服务的常用模块设计思路。
相关资源
本书提供源码下载、读者交流群等服务,详情请参见本书封底的读者服务信息。
若想获取关于高性能服务器开发的更多知识,可以关注笔者的两个微信公众号:“高性能服务器开发”和“程序员小方”。
致谢
感谢笔者的妻子承担家务及照顾笔者的生活,让笔者可以集中精力写作本书。
感谢各位同事帮助笔者成长与提高。
感谢王旭东等同学为本书的校对和勘误做出贡献,感谢“高性能服务器开发”群内小伙伴们的支持。
感谢电子工业出版社工作严谨、高效的张国霞编辑,她在成书过程中对笔者的指导、协助和鞭策,是本书得以完成的重要助力。