《Linux 多线程服务端编程:使用 muduo C++ 网络库》勘误表

回首页

最后更新:2016-09-16

内容订正(按页次排列)

p.16 代码L61 (表述严密) 2013-01-11
误:// 提升成功,现在引用计数值至少为 2……
正:// 提升成功,现在引用计数值几乎总是大于等于 2……
感谢:bertyoung

p.47 第 1 行(typo) 2014-10-08
误:生成代码
正:生产代码
感谢:choudan

p.54 最后一段代码中定义 requests (缺分号) 2013-02-12

void Inventory::printAll() const
{
  std::set<Request*> requests;

感谢:研究员Raywill

p.59 倒数第 2 行(typo) 2013-07-04
误:“进程(process)”是操作里最重要的两个概念之一
正:“进程(process)”是操作系统里最重要的两个概念之一
感谢:黄珏珅Tony

p.80 倒数第 3 行(typo) 2013-03-17
误:8. 除了你推荐的 Reactor + thread poll
正:8. 除了你推荐的 Reactor + thread pool
感谢:Hoterran

p.89 第 4.3 节第 1 行(typo) 2014-01-11
误:pthread_self 函数用于返回当前进程的标识符
正:pthread_self 函数用于返回当前线程的标识符
感谢:meihaifeng

p.93 倒数第 2 段结尾(更新) 2013-02-08
误:如果 Thread 对象的生命期短于线程,那么就没有机会释放 pthread_t 了。
正:如果 Thread 对象的生命期短于线程,那么析构时会自动 detach 线程,避免了资源泄漏。
说明:muduo 0.9.2 修正了此问题。

p.99 第 4 段(更新) 2013-06-21
原文:Linux 文档并没有说明:当一个线程正阻塞在 epoll_wait() 上时,另一个线程往此 epoll fd 添加一个新的监视 fd 会发生什么。新 fd 上的事件会不会在此次 epoll_wait() 调用中返回?
改为:Linux 文档并没有说明:当一个线程正阻塞在 epoll_wait() 上时,另一个线程修改此 epoll fd 的事件关注列表(watch list)会发生什么。

说明:我在 2012 年写这一段的时候参考了 Debian 6.0 和 Ubuntu 10.04/12.04 的 man epollman epoll_wait,当时的手册没有说明多线程操作同一个 epoll fd 会发生什么情况。后来 man epoll_wait 增加了一段说明
While one thread is blocked in a call to epoll_pwait(), it is possible for another thread to add a file descriptor to the waited-upon epoll instance. If the new file descriptor becomes ready, it will cause the epoll_wait() call to unblock.
这段新的描述也可以在 Debian 7.0 的手册中找到。 手册更新历史见:
https://bugzilla.kernel.org/show_bug.cgi?id=43072
http://man7.org/linux/man-pages/changelog.html#release_3.39

这不影响后面的结论:为了稳妥起见,我们应该把对同一个 epoll fd 的操作(添加、删除、修改、等待)都放到同一个线程中执行,这正是我们需要 muduo::EventLoop::wakeup() 的原因。

p.110 第 12 行(typo) 2016-09-16
误:logfile_test.2012060-144022.hostname.3605.log
正:logfile_test.20120603-144022.hostname.3605.log
感谢:梁少聪

p.161 表 6-1 方案 8(typo) 2013-03-17
误:reactor + thread poll
正:reactor + thread pool
感谢:Hoterran

p.183 第 4 行(typo) 2014-03-30
误:L57 在连接建立时发生第一次数据;
正:L57 在连接建立时发送第一次数据;
感谢:xanpeng

p.204 倒数第 5 行(typo) 2014-03-30
误:没有人真的会用轮询(busy-pooling)来检查
正:没有人真的会用轮询(busy-polling)来检查
感谢:xanpeng

p.241 倒数第 7 行 2013-07-19
误:clock_gettime(2) 精度最高,但是其系统调用的开销比 gettimeofday(2) 大。
正:clock_gettime(2) 精度最高,gettimeofday(2) 同时纳入候选。
说明:在较新的 Linux 内核上,clock_gettime()gettimeofday() 都不是系统调用,开销相当。 在比较旧的内核(例如 2.6.18)上, clock_gettime() 是系统调用,开销较大。

p.289 正文第 3 行 2013-05-10
误:这个程序利用 Channeltimerfd 的 readable 事件转发给 timerout() 函数。
正:这个程序利用 Channeltimerfd 的 readable 事件转发给 timeout() 函数。
感谢:寒流

p.294 第一段代码第 117 行末尾(typo) 2014-03-19
误:// BuardedBy mutex_
正:// GuardedBy mutex_
感谢:xanpeng

p.348 倒数第 2 行(typo) 2013-02-18
误:Master 指定某个 Work
正:Master 指定某个 Worker

p.359 图 9-11 2013-02-06
修改为:
图 9-11
说明:Sender 和 Receiver 的时钟不一定严格对准,可能存在微小误差, 这通常不会对心跳检测造成影响。但是在闰秒期间,时间有可能回退(rewind), 而且多台机器的时间回退不是同步发生的,那么会放大时间差异,可能引起误判。

p.367 第 12 行(typo) 2014-04-03
误:增加一个 RFC 调用
正:增加一个 RPC 调用
感谢:xanpeng

p.405 第 4 行、第 10 行(typo) 2015-08-20
误:交叉应用
正:交叉引用
感谢:choudan

p.422 脚注 87 2013-02-20
误:如果处于测试目的
正:如果出于测试目的
感谢:Gui

p.524 代码第 4 行(typo) 2014-03-16
误:dlsym(RTDL_NEXT, "connect");
正:dlsym(RTLD_NEXT, "connect");

p.525 第 2 行末尾(typo) 2014-03-16
误:dlsym(RTDL_NEXT,
正:dlsym(RTLD_NEXT,

p.574 第 14 行 2013-03-01
误:几百幅收发 package 的时序图。
正:几百幅收发 packet 的时序图。

补充内容(按页次排列)

p.iii 第 3 段开头 2013-01-25
读者应该已经大致读过《现代操作系统》、《UNIX 环境高级编程》、《UNIX 网络编程》、《C++ Primer》或与之内容相近的书籍,熟悉基本概念,并掌握 Pthreads 和 Sockets API 的常规用法

p.18 第 1 段代码之后 2013-02-04
globalPtr 能被多个线程看到,那么它的读写需要加锁。具体 race condition 分析见 http://blog.csdn.net/solstice/article/details/8547547

p.35 第 2 段开头 2013-02-09
C++ 没有 annotation(除非给编译器打补丁,见 http://llvm.org/devmtg/2011-11/#talk3,……

p.35 第2.1.2节之前 2013-02-18
Linux 的 PTHREAD_MUTEX_ADAPTIVE_NP 与此类似。
说明:Linux 的 Pthreads mutex 可以指定为 PTHREAD_MUTEX_ADAPTIVE_NP 类型, 以结合 spin lock 和普通 mutex。这里的 _NP 是 non-portable 的缩写, 表明它是 Linux 专有的,而非 POSIX 规定的。

p.269 最后一行之后 2013-07-08
增加:Channel 的简单使用示例可参考 examples/roundtrip/roundtrip_udp.cc

p.347 最后一行之前 2013-02-16
并且 Thumbnailer 应该自带负载保护,使其能从全面故障中自动恢复。
说明:假如某种原因使得所有的 Thumbnailer 都退出或失去联系, 那么故障恢复过程中新启动的第 1 个 Thumbnailer 会收到来自全部 clients 的请求 (就算同时启动 4 个 Thumbnailer 也会有先后差别,clients 不会同时一次性拿到 4 个新的服务地址)。 如果没有负载保护,那么会造成“启动一个压垮一个”的后果,系统长时间无法恢复。

p.542 在 12.7.2 标题之前 2013-01-21
增加:对于 64-bit 中的 std::vector 也可以采用类似的做法, 让对象大小减为 16 字节,max_size() 也会相应缩小。

p.563 A.1.3 第3段(增加年月) 2013-01-22
10 年后的今天(本文写于 2011 年 6 月),事情起了一些变化,……

p.567 A.1.8 第2点(增加文献) 2013-10-04
为了避免所谓的内存碎片而自己实现 memory pool 似乎已经不再流行了,参考《The Memory Fragmentation Problem: Solved?》(http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.141.4610

格式调整(按页次排列)

p.474 L13 (斜体) 2012-12-30
误:可不可以退回 n 字节?
正:可不可以退回 n 字节?

p.521 L1 (等宽) 2012-12-30
误:注意到 Ruby 的 Fixnum 整数……
正:注意到 Ruby 的 Fixnum 整数……

 

留言

blog comments powered by Disqus