《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册

Linux 多线程服务器端编程:使用 muduo C++ 网络库 目录 一、线程同步精要 互斥器 mutex 条件变量 封装 MutexLock、MutexLockGuard 和 Condition 线程安全的 Singleton 实现 mutex 与 shared_ptr 的应用实例 一、线程同步精要 并发编程的两种基本模型:message passing 和 shared memory。 线程同步的四项原则: 尽量最低限度的共享对象... 阅读详情

《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册

《Linux多线程服务端编程:使用muduo C++网络库》这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错的成绩。本书购买方式见配套网站 http://chenshuo.com/book 。

以下谈一谈这本书的写作背景与内容取舍的原因。

参加工作以来,我编写并维护了若干C++/Java多线程网络服务程序,这本书总结了我在开发维护这类服务程序方面的经验。工作中,我没有写过单线程的网络服务程序,没有写过C语言的网络服务程序,也没有写过运行在Windows下的网络服务程序,因此本书不涉及这些内容。

在“Linux服务端开发”这一背景下,这本书主要讲三个方面的内容[1]:现代C++、多线程、网络编程,分别对应书的第3、1、2部分。这不是一本入门书,本书的读者应该在以上三方面已经具备相当的基础[2]:网络编程方面,能轻松读懂6.1节的两个Python程序;C++方面,对12.8节的代码不感到陌生;多线程方面,能明白第1章要解决什么问题。

第9章“分布式系统工程实践”详细介绍了这本书的应用背景,即开发公司内部的分布式服务系统,书中的很多决策(design decision)和技术取舍(trade-off)是在这一应用场景下做出的。以下是各章直接的交叉引用关系图(没有计算引用次数),其中第0章是前言,字母章节是附录。可见第9章是被引用最多的一章,某种意义上可以说第9章既是本书的先决条件,又是本书的终极目标。由于章节之间存在众多的交叉引用,去掉任何一章都会破坏内容的完整性。

ref

这本书的书名原本打算叫“Linux C++ 多线程系统编程”。写完之后发现,与其他Unix/Linux系统编程方面的书不同,这本书有明确的应用场景,因此可以砍掉很多内容,突出重点。甚至可以说我主要讲别的书没有讲到的内容。这不是一本面面俱到的书,因此最终的书名也就不叫“系统编程”了。

同时,我认为很多教科书上介绍的一些做法是过时的(signal),一些是不推荐使用的(从外部终止线程、TCP OOB数据),一些是大多数情况下没必要使用的(内存池、lock-free 编程)。作为全面的教材和手册,把这些内容放进去可以理解。但是这本书定位是经验总结,我略去了教科书上那些基本用不到的知识点,以免喧宾夺主,也建议读者不要把精力花在那些次要问题上。

  • 这本书没有花很大的篇幅去讲signal,而是在第4.10节说明多线程程序不要使用signal作为IPC。并且,在muduo-protorpc的示例中给出了Linux专有的signalfd(2)的用法,可以避免传统signal handler的常见陷阱,也更符合UNIX的“everything is a file”哲学。第4.4节说明不要从外部终止线程,因此也就不必去细究Pthreads cancellation point了。多线程程序最好不要fork()(第4.9节)。
  • 这本书没介绍daemon进程,我认为daemon是过时的做法。因为daemon进程的父进程是init(1),配置文件在本机,不便于多机统一监控与管理(第9.8节)。(注:如果是第三方标准的服务程序,又不需要经常升级或改配置重启,并且一旦崩溃,重启就能继续服务,那么做成 daemon 让init(1)接管是可以的,比如ntpd、sshd等。这里谈的是自己开发维护的服务程序。)另外,Java/Python/Go写的服务程序似乎也没有做成daemon的习惯,C++程序没有理由要特殊对待。补充一点,Linux的进程管理机制很落后(从UNIX继承而来),子进程退出的事件只能被父进程以SIGCHLD信号的方式收到(而且这个signal可能丢失),kill(pid) 也存在很多race condition(你怎么保证pid在kill之前的一瞬间还代表你想kill的那个进程,而不是一个新启动的进程?close(fd)就不会有这种 race condition。)。这些困难在用户态无法克服,只能修改内核,引入新的系统调用才能治本。例如 FreeBSD 9.0 引入了 pdfork()/pdkill() 等,将子进程变成文件描述符,这样就能用IO事件框架统一处理了,也符合UNIX的“everything is a file”哲学。但愿Linux内核也能尽快引入类似的系统调用,减轻程序员的负担。
  • 这本书没有讲内存池,而是说明不是每个程序都要自己写内存池(§12.2.8)。这本书也没有把“避免内存碎片”挂在嘴边,而是论证为什么一般的程序不必在意它(§A.1.8);
  • 这本书只关注Linux,不考虑移植性。它推荐使用Linux专有的gettid()系统调用作为线程标识(第4.3节),而不是用pthread_self()。
  • 这本书不讲POSIX中五花八门的定时函数,而专讲用Linux特有的timerfd来实现高精度定时(§7.8.2),因为它能方便地融入IO事件处理框架。muduo直接使用C++标准库来管理定时器,而不是自己实现小顶堆(heap),这样可以简化实现(§8.2.1)。
  • 这本书只讲mutex和condition variable作为最基础的线程同步手段(第2章),并且我认为一个C++多线程程序代码里不应该直接出现pthread_mutex_lock之类的基本Pthreads调用。本书进一步建议只使用非递归的mutex(§2.1.1),这与某些网上文章的推荐正好相反。这本书第2.3节甚至建议不要使用读写锁和信号量(semaphore),因为一是容易用错,二是不见得能提高性能。mutex和condition variable是完备的,能实现多种更易用的同步设施,例如CountDownLatch和BlockingQueue。§12.8.3的代码展示了用BlockingQueue和ThreadPool控制并发度的手法,做到了“No locks. No condition variables. No callbacks.”
  • 这本书不讲lock-free编程,因为编写可靠的lock-free代码并分析验证其正确性的难度远大于编写普通的使用mutex和condition variable的多线程代码,后者已经有了相当成熟的理论和工具。我认为lock-free不是每个多线程程序员应该掌握的技术,它投入高而用处少,可以适当了解,但不值得每个人都去深究。只需要少数人用它实现封装好的数据结构,像我这样的普通人就可以受益。
  • 这本书只讲BSD Sockets作为进程间通信的手段,并且只用TCP长连接(§3.4)。这样就砍掉了pipe、FIFO、POSIX message queue、shared memory、STREAMS、UNIX domain socket等等内容,因为它们都只限本机进程间通信,无法扩展到多机。
  • 网络编程方面(第6、7章),这本书不讲Sockets API的基本用法,而且代码中也不会直接使用它们。我认为在程序中直接使用 Sockets API是初学者的做法,当写一个新网络服务程序,如果一开始考虑的是怎么组织accept、read、epoll_wait等调用,这种做法无异于用铅笔刀锯大树,事倍功半,也不利于将来的功能扩展和维护。稍微像样点的公司都会用成熟的网络库(不一定开源),把网络编程的复杂性封装进去,暴露出良好易用的接口,让开发人员使用更高层的building blocks(消息传递或RPC)从功能的角度去设计程序,避免一次次反复掉到TCP网络编程的坑里。多个服务程序共享相同的基础库和事件处理框架的益处是显而易见的,一方面把网络编程的复杂性集中到一起,避免每个团队都去踏一遍坑;另一方面,基础库的bug修复与性能优化能惠及用到它的全部服务程序;最后,程序结构上的相似性让编程经验更加通用,多个服务程序在功能、性能、正确性等方面具有共性,能举一反三触类旁通,降低将来开发维护的成本。应该避免每个程序都另起炉灶,单独设计其IO事件处理结构。
  • 这本书只讲非阻塞IO结合IO复用(IO-Multiplexing)这一种并发风格(归纳为三个半事件),并介绍在多线程下的扩展(one loop per thread)。IO复用方面,本书只讲level-trigger,不讲edge-trigger。一方面目前没有up to date的测试表明ET更快,相反,我认为LT在读取数据时可以节约一次read()调用(§8.7.2);另一方面,LT模式更容易与其他第三方库结合(§7.15)。多线程程序管理并发socket fd有很多风格可供选择,例如epoll fd是多个线程共享一个(多对一)还是每个线程有自己的epoll fd(一对一),每个socket fd是只属于一个epoll fd(多对一)还是可以同时属于多个 epoll fd(多对多),每个socket fd是只能被固定的一个线程读写还是可以被多个线程读写(如果是后者,那么读写的时候是加锁还是使用ONESHOT)。以上不是每种都可行,本书也没有一一加以分析,而是建议使用one loop per thread这种适用性较强的风格,首先是正确性容易验证,其次是性能也能满足要求。
  • 本书不讲IPv6,因为目前世界上最大的公司的服务机群也用不完一个私有A类地址(10.0.0.0/8)。本书不讲UDP,因为《Unix网络编程》已经讲得很好了。
  • 这本书举的网络编程的例子不再是简单的echo服务,而是有格式(因此引入codec)、多连接之间会交换数据的网络程序,更接近业务场景,也借机讲解如何避免TCP网络编程的常见陷阱。并且在示例代码中给出了分布式单词计数、多机求中位数等稍微复杂一点的程序。
  • 在C++方面,这本书没有介绍动态链接库热更新这种“高级”技术,而是说明,在分布式系统中,为了部署方便,应该从源码编译全部的库,与主程序链接为一个standalone的可执行文件,以减小对运行环境的依赖(第10章)。第11章还讨论了程序库与应用程序之间的接口设计。

“信息”按照香农的定义,是“减少不确定性”,这本书包含的信息正是减少选用编程设施(facilities)方面的不确定性,让读者集中精力攻克本质问题。这本书介绍的方法不一定对于每个应用场景都是最好的,但肯定是简便易行的,是时间成本、功能、性能的一种合理折中。


[1] 这本书前言的第一句话“本书主要讲述采用现代 C++ 在 x86-64 Linux 上编写多线程 TCP 网络服务程序的主流常规技术”,封面印着“示范在多核时代采用现代 C++ 编写多线程 TCP 网络服务器的正规做法”。

[2] 前言写到:读者应该已经大致读过《现代操作系统》、《UNIX 环境高级编程》、《UNIX 网络编程》、《C++ Primer》或与之内容相近的书籍,熟悉基本概念,并掌握 Pthreads 和 Sockets API 的常规用法。

Linux多线程服务端编程与muduo网络库实践 在多线程服务端编程中,线程是程序执行流的最小单元,允许并发执行。相比之下,进程则是资源分配的最小单位,拥有独立的地址空间。在多核处理器环境下,多线程能有效利用CPU资源,提高程序的并发处理能力。在Linux系统中,I/O模型主要分为以下几种类型:阻塞I/O(Blocking I/O)非阻塞I/O(Non-blocking I/O)I/O复用(I/O Multiplexing)信号驱动式I/O(Signal-driven I/O) 阅读详情

相关推荐

Muduo: 高效Linux多线程服务器C++网络库使用指南

Linux平台上的C++网络库为开发者提供了强大的网络通信能力,是构建高性能网络应用不可或缺的组件。在本章中,我们将对Linux平台下常用的几种C++网络库进行介绍,它们包括但不限于Boost.Asio、Muduo、Poco等。我们会概述各个网络库的设计理念、核心功能和使用场景,帮助读者选择适合自己项目需求的网络库。首先,我们将简要讨论网络库的历史和发展,以及它们如何应对网络编程中常见的挑战。接下来,我们将深入了解几个主要网络库的架构和它们提供的核心组件,例如IO多路复用器、定时器、缓冲区管理等。

weixin_31459297的博客 812

《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册...

《Linux多线程服务端编程:使用muduo C++网络库》这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错的成绩。本书购买方式见配套网站 http://chenshuo.com/book 。 以下谈一谈这本书的写作背景与内容取舍的原因。 参加工作以来,我编写并维护了若干C++/Java多线程网络服务程序,这本书总...

weixin_34238642的博客 224

Linux多线程服务端编程

Linux多线程服务端编程是陈硕大神的一本linux服务端开发实战书籍。

陈硕《Linux多线程服务端编程》中的EventLoop Reactor 的 c++11 版本

把原书第8章的例子《设计Reactor——如何从头开始编写非阻塞网络库》 地址:https://github.com/chenshuo/recipes/tree/master/reactor 用 c++11 搞了一遍,并且简化到全部代码放在一个文件中,方便察看。 步骤0:什么都不做的 event loop 事件循环 EventLoop, assertInLoopThread() 这个步...

found的专栏 1075

顶刊级科研绘图技巧

顶刊级科研绘图技巧

2401_89571885的博客 1157

安川机器人SOCKET 通讯

命令 功能 参数 示例 返回 SelectJob 选择程序 JobName LineNo SelectJob TEST 0 #SelectJob,Ok StartJob 启动程序 JobName StartJob TEST #StartJob,Ok Pause 暂停当前程序 - Pause #Pause,Ok Continue 继续当前程序 - Continue #Continue,Ok ServoOn 伺服上电 - ServoOn #ServoOn,Ok ServoOf...

记录学习内容 8285

Muduo网络库源码分析(三)线程间使用eventfd通信和EventLoop::runInLoop系列函数

先说第一点,线程(进程)间通信有很多种方式(pipe,socketpair),为什么这里选择eventfd? eventfd 是一个比 pipe 更高效的线程间事件通知机制,一方面它比 pipe 少用一个 file descripor,节省了资源;另一方面,eventfd 的缓冲区管理也简单得多,全部“buffer” 只有定长8 bytes,不像 pipe 那样可能有不定长的真正 buf

NK_test的博客 1万+

TSMC40nmLP版图实战:从Design Rule解读到Cadence高效布局布线

本文详细解析了TSMC40nmLP工艺的版图设计实战,从Design Rule解读到Cadence高效布局布线技巧。重点介绍了40nm工艺中的关键设计规则,如最小线宽、间距规则和深N阱规则,并分享了Cadence Virtuoso中的高效工作流和射频模块设计技巧,帮助工程师提升版图设计效率和质量。

weixin_29250403的博客 378

C++Muduo网络库:简介及使用

Muduo网络库:底层实质上为Linux的epoll + pthread线程池,且依赖boost库。 muduo的网络设计核心为一个线程一个事件循环,有一个main Reactor负载accept连接,然后把连接分发到某个sub Reactor(采用轮询的方式来选择sub Reactor),该连接的所用操作都在那个sub Reactor所处的线程中完成。多个连接可能被分派到多个线程中,以充分利用CPU,Reactor poll的大小是固定的,根据CPU的数目确定。如果有过多的耗费CPU I/O的计算任务,可

Rain的博客 1万+

如何利用URDF文件表示并联结构(仅适用于支持SDF格式的仿真环境)

介绍了一种使用URDF文件在Gazebo中表示并联结构的方法,该方法使用了URDF的SDF拓展。在一个具有并联结构的双足机器人上应用并演示了此方法的有效性。

RobotFreak的博客 3851

PHP 对接建行生活订单推送接口

php对接建行订单推送

qq_43647026的博客 561

【亲测免费】 探索Linux多线程服务端编程的奥秘:陈硕的经典之作

探索Linux多线程服务端编程的奥秘:陈硕的经典之作 【下载地址】Linux多线程服务端编程资源下载分享 Linux多线程服务端编程资源下载 项目地址: https://gitcode.com/Open-source-docume...

gitblog_06699的博客 745

WSL基础环境配置方案

通过以上步骤,您已经在 Windows 的 WSL 环境中成功搭建了一个完整的基础开发环境,包含 Docker、Kubernetes、Helm、kubectl、yq、Git 等工具。这套环境特别适用于在国内使用阿里云镜像服务部署和管理 Tekton,提升了开发和运维的效率和稳定性。

落魄书生的职业学习生涯 8876

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第一章 线程安全的对象生命期管理

编写线程安全的类不是难事,用同步原语(synchronization primitives)保护内部状态即可。但对象的生与死不能由对象自身拥有的mutex(互斥器)来保护。如何避免对象析构时可能存在的race condition(竞态条件)是C++多线程编程面临的基本问题,可以借助Boost库的shared_ptr和weak_ptr完美解决,这也是实现线程安全的Observer模式(观察者模式,它是一种行为设计模式,用于定义对象之间的一对多依赖关系,以便当一个对象的状态发生变化时,其所有依赖对象都会得到通知

tus00000的博客 1018

javafx结合Scene Builder自定义fxml实现漂亮的登录界面、自定义最小化、关闭按钮

本节主要介绍了如何结合Scene Builder工具来制作一个好看又漂亮的登录界面,以及介绍了如何在程序中调用生成界面文件fxml文件,如何获取到fxml文件中的组件等,并演示登录、最小化和关闭等功能。

c1007857613的专栏 5222

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第六章 muduo网络库简介

2010年3月作者写了一篇《学之者生,用之者死——ACE历史与简评》(http://blog.youkuaiyun.com/Solstice/archive/2010/03/10/5364096.aspx,ACE是(Adaptive Communication Environment)是一个C++编写的开源框架,用于开发高性能、可伸缩、分布式系统的网络应用),其中提到了作者心目中理想的网络库的样子: 1.线程安全,原生支持多核多线程。 2.不考虑可移植性,不跨平台,只支持Linux,不支持Windows。 3.主要支持

tus00000的博客 1134

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Linux多线程服务端编程:使用muduo C++网络库学习之环境配置(VS2019跨平台开发)

本篇记录《Linux多线程服务端编程:使用muduo C++网络库》在ubuntu1804系统上开发环境的配置,包括cmake的安装,boost库的安装与测试,muduo网络库的编译,安装与测试,以及用VS2019开发Linux程序的配置。

chenyijun的专栏 1113

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

【免费下载】 Linux多线程服务端编程资源下载

Linux多线程服务端编程资源下载 【下载地址】Linux多线程服务端编程资源下载分享 Linux多线程服务端编程资源下载 项目地址: https://gitcode.com/Open-source-documentation-t...

gitblog_06640的博客 902

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 附录A 谈一谈网络编程学习经验

本文谈一谈作者在学习网络编程方面的一些个人经验。“网络编程”这个术语的范围很广,本文指用Sockets API开发基于TCP/IP的网络应用程序,具体定义见A.1.5 “网络编程的各种任务角色”。 受限于作者的经历和经验,本附录的适应范围是: 1.x86-64 Linux服务端网络编程,直接或间接使用Sockets API。 2.公司内网。不一定是局域网,但总体位于公司防火墙之内,环境可控。 文本可能不适合: 1.PC客户端网络编程,程序运行在客户的PC上,环境多变且不可控。 2.Windows网络编程。

tus00000的博客 1268

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第九章 分布式系统工程实践(上)

本章谈的分布式系统是指运行在公司防火墙以内的信息基础设施(infrastructure),用于对外(客户)提供联机信息服务,不是针对公司员工的办公自动化系统。服务器的硬件平台是多核Intel x86-64处理器、几十GB内存、千兆网互联、常规存储、运行Linux操作系统。系统的规模大约在几十台到几百台,可以位于一个机房,也可以位于全球的多个数据中心。只有两台机器的双机容错(热备)系统不是本章的讨论范围。服务程序是普通的Linux用户进程,进程之间通过TCP/IP通信。特别是,本章不考虑分布式存储系统,只考虑

tus00000的博客 750

Linux多线程服务端编程:使用muduo C++网络库

常见的并发网络服务程序设计方案 W. Richard Stevens 的《UNIX 网络编程(第2 版)》第27 章“Client-ServerDesign Alternatives”介绍了十来种当时(20 世纪90 年代末)流行的编写并发网络程序的方案。[UNP] 第3 版第30 章,内容未变,还是这几种。以下简称UNP CSDA方案。[UNP] 这本书主要讲解阻塞式网络编程,在非阻塞方面着墨

博文视点(北京)官方博客 4373
上一篇: 用 LaTeX 排版编程技术书籍的一些个人经验
下一篇: 近期微博吐槽言论存档,涉及“性能优化”、C++陋习等
陈硕
博客等级 码龄26年 1万+粉丝 144原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值