我们假定读者掌握了:

  1. Linux环境下C/C++的系统编程和基本的socket编程方法
  2. 操作系统基本概念以及Linux的基本概念和原理
  3. Linux进程和线程的内存地址空间布局和资源关系

我们谈什么,不谈什么:

  1. Linux下的网络程序设计所遵循的规范
  2. Linux网络程序的工作模型和原理
  3. 一般性质上的网络协议设计方法和原则
  4. 基本上只针对Linux,基本不涉及Windows
  5. 只涉及TCP协议的通信,不谈UDP

可以先行阅读的参考资料:
进程眼中的线性地址空间
线程眼中的线性地址空间
Linux线程的前世今生
聊聊内存管理
Linux系统调用
goroutine背后的系统知识


Read More

这篇文章我们聊聊内存管理。

本来我想不针对于任何具体的操作系统来谈内存管理,但是又觉得不接地气、言之无物。所以我决定在阐述概念的同时,还针对IA32平台Linux下的内存管理做简要的介绍,并且以实验来证明结论。以下内容分拆为几个大标题和小节,内容前后承接。

物理地址空间

首先,什么是物理地址空间?我们知道CPU与外部进行信息传递的公用通道就是总线,一般而言,CPU有三大总线:控制总线、数据总线、地址总线。这三类总线在一定程度上决定了CPU对外部设备的控制和数据传送能力。其中地址总线决定了CPU能向外部输出的地址宽度,也就是CPU的寻址能力。

通过/proc/cpuinfo可以查看具体的数据:

本文只需要关心红色框内的信息即可,我的CPU拥有36位地址总线,其寻址范围是2^36=64G. 那么其物理上理论能编址的上限就是这么大了。关于48 bits virtual的相关信息以及64 bit的现有实现,则可以参考这里

Read More

很久没更新博客了,虽然说一直都在做事情也没虚度,但是内心多少还是有些愧疚的。忙碌好久了,这个周末写篇文章放松下。

言归正传,这次我们来聊一聊多核CPU运行多线程程序时,可能会产生的一种性能衰退现象——False Sharing. 貌似很高大上?No No No,我相信看完这篇文章之后你会完全理解False Sharing,并且能够在设计和编写多线程程序的时候意识到并完美解决这个问题。

OK,我们开始吧。

首先,False Sharing的产生需要几个特定条件:CPU具有多个核心,其上运行着的同一个程序的多个线程分别运行在不同的核心上,而且这些线程在修改同一个cache行的数据。说到这里你可能已经明白了,就是多核心修改同一cache行引起的。没错,因为现代CPU的每个核心都有自己的私有cache块,False Sharing产生的原因就是因为某个核心的线程修改了自己私有cache某行的数据,导致另一个核心的私有cache中映射到同样内存位置的cache行也被标记上脏位而被迫逐出,又一次从内存更新的缘故(保证cache一致性)。

如果两个核心运行的线程“此起彼伏”的修改邻近内存的数据,就会相互导致对方的私有cache中映射到该内存位置的cache行被频繁的更新。这样的话,cache的效果根本就没有体现出来。原理见下图:

Read More

最近学习网络层协议的时候,注意到了IP协议中数据包分片的问题。下图是IP协议头的数据字段的示意:

如图所示,IP协议理论上允许的最大IP数据报为65535字节(16位来表示包总长)。但是因为协议栈网络层下面的数据链路层一般允许的帧长远远小于这个值,例如以太网的MTU(即Maximum Transmission Unit,最大传输单元)通常在1500字节左右。所以较大的IP数据包会被分片传递给数据链路层发送,分片的IP数据报可能会以不同的路径传输到接收主机,接收主机通过一系列的重组,将其还原为一个完整的IP数据报,再提交给上层协议处理。上图中的红色字段便是被设计用来处理IP数据包分片和重组的。

那么,这三个字段如何实现对分片进行表示呢?

Read More