最后更新:2022-07-31
p.15 第 11 行 (typo) 2019-06-01
误:自动记住用缓冲区的长度,
正:自动记住可用缓冲区的长度,
感谢:ling jiang
p.15 倒数第 7 行 (typo) 2022-04-05
误:都是值语意,
正:都是值语义,
感谢:Qingchuan Zhang
p.16 代码L61 (表述严密) 2013-01-11
误:// 提升成功,现在引用计数值至少为 2……
正:// 提升成功,现在引用计数值几乎总是大于等于 2……
感谢:bertyoung
p.20 第 10 行 (typo) 2019-06-01
误:并且 Foo 对象的由动态库中的 Factory 构造,
正:并且 Foo 对象由动态库中的 Factory 构造,
感谢:ling jiang
p.32 第 8 行 (typo) 2022-04-05
误:C# 的 using 语句
正:C# 的 lock 语句
感谢:Qingchuan Zhang
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.79 倒数第 5 行(typo) 2020-12-14
误:同额外的线程专门做 memcached 的 IO,
正:用额外的线程专门做 memcached 的 IO,
感谢:Yikarus
p.80 倒数第 3 行(typo) 2013-03-17
误:8. 除了你推荐的 Reactor + thread poll,
正:8. 除了你推荐的 Reactor + thread pool,
感谢:Hoterran
p.89 第 7 行(typo) 2020-06-20
误:调用之前向 stdout 输出其他字符。
正:调用之间向 stdout 输出其他字符。
感谢:梅绍明
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 epoll
及
man 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.213 倒数第 6 行(typo) 2019-06-01
误:使用 vector 的另一个好处是它的 capcity() 机制减少了内存分配的次数。
正:使用 vector 的另一个好处是它的 capacity() 机制减少了内存分配的次数。
感谢:Corexoryummy
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.243 倒数第 5 行(typo) 2019-06-01
误:因此这些操作的事件复杂度是
正:因此这些操作的时间复杂度是
感谢:胡浩
p.289 正文第 3 行 2013-05-10
误:这个程序利用 Channel
将 timerfd
的 readable 事件转发给 函数。timerout()
正:这个程序利用 Channel
将 timerfd
的 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
修改为:
说明:Sender 和 Receiver 的时钟不一定严格对准,可能存在微小误差,
这通常不会对心跳检测造成影响。但是在闰秒期间,时间有可能回退(rewind),
而且多台机器的时间回退不是同步发生的,那么会放大时间差异,可能引起误判。
p.367 第 12 行(typo) 2014-04-03
误:增加一个 RFC 调用
正:增加一个 RPC 调用
感谢:xanpeng
p.405 第 4 行、第 10 行(typo) 2015-08-20
误:交叉应用
正:交叉引用
感谢:choudan
p.405 第 15 行(typo) 2017-09-29
误:记到一张之上。
正:记到一张纸上。
感谢:Li Zhirui
p.422 脚注 87 2013-02-20
误:如果处于测试目的
正:如果出于测试目的
感谢:Gui
p.478 第 5 行(typo) 2021-07-27
误:ostreamstream 有时候比 snprintf() 快
正:ostringstream 有时候比 snprintf() 快
感谢:xris1658
p.479 倒数第 7 行(typo) 2022-05-14
误:return s;
正:return os;
感谢:Wandong Weng
p.483 第 1 行 (typo) 2019-06-01
误:等等类型也都是值语意,
正:等等类型也都是值语义,
感谢:ling jiang
p.493 第 3 行 (typo) 2019-06-01
误:因为这样一来 ADS class 的拷贝就失去意义了。
正:因为这样一来 ADT class 的拷贝就失去意义了。
感谢:ling jiang
p.494 第 1 行 (typo) 2019-06-01
误:如果语言支持显示控制对象的生命期
正:如果语言支持显式控制对象的生命期
感谢:ling jiang
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
整数……