支撑百万并发的“零拷贝”技术,你了解吗?

拷贝(Zero-copy)技术指在计算机执行操作时,CPU 不需要先将数据从一个内存区域复制到另一个内存区域,从而可以减少上下文切换以及 CPU 的拷贝时间 。
它的作用是在数据报从网络设备到用户程序空间传递的过程中,减少数据拷贝次数,减少系统调用,实现 CPU 的零参与,彻底消除 CPU 在这方面的负载 。
实现零拷贝用到的最主要技术是 DMA 数据传输技术和内存区域映射技术:

  • 零拷贝机制可以减少数据在内核缓冲区和用户进程缓冲区之间反复的 I/O 拷贝操作 。
  • 零拷贝机制可以减少用户进程地址空间和内核地址空间之间因为上下文切换而带来的 CPU 开销 。
物理内存和虚拟内存
由于操作系统的进程与进程之间是共享 CPU 和内存资源的,因此需要一套完善的内存管理机制防止进程之间内存泄漏的问题 。
为了更加有效地管理内存并减少出错,现代操作系统提供了一种对主存的抽象概念,即虚拟内存(Virtual Memory) 。
虚拟内存为每个进程提供了一个一致的、私有的地址空间,它让每个进程产生了一种自己在独享主存的错觉(每个进程拥有一片连续完整的内存空间) 。
物理内存
物理内存(Physical Memory)是相对于虚拟内存(Virtual Memory)而言的 。
物理内存指通过物理内存条而获得的内存空间,而虚拟内存则是指将硬盘的一块区域划分来作为内存 。内存主要作用是在计算机运行时为操作系统和各种程序提供临时储存 。
在应用中,自然是顾名思义,物理上,真实存在的插在主板内存槽上的内存条的容量的大小 。
虚拟内存
虚拟内存是计算机系统内存管理的一种技术 。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间) 。
而实际上,虚拟内存通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换,加载到物理内存中来 。
目前,大多数操作系统都使用了虚拟内存,如 windows 系统的虚拟内存、linux 系统的交换空间等等 。
虚拟内存地址和用户进程紧密相关,一般来说不同进程里的同一个虚拟地址指向的物理地址是不一样的,所以离开进程谈虚拟内存没有任何意义 。每个进程所能使用的虚拟地址大小和 CPU 位数有关 。
在 32 位的系统上,虚拟地址空间大小是 2^32=4G,在 64 位系统上,虚拟地址空间大小是 2^64=16G,而实际的物理内存可能远远小于虚拟内存的大小 。
每个用户进程维护了一个单独的页表(Page Table),虚拟内存和物理内存就是通过这个页表实现地址空间的映射的 。
下面给出两个进程 A、B 各自的虚拟内存空间以及对应的物理内存之间的地址映射示意图:
 
支撑百万并发的“零拷贝”技术,你了解吗?

文章插图
 
 
当进程执行一个程序时,需要先从内存中读取该进程的指令,然后执行,获取指令时用到的就是虚拟地址 。
这个虚拟地址是程序链接时确定的(内核加载并初始化进程时会调整动态库的地址范围) 。
为了获取到实际的数据,CPU 需要将虚拟地址转换成物理地址,CPU 转换地址时需要用到进程的页表(Page Table),而页表(Page Table)里面的数据由操作系统维护 。
其中页表(Page Table)可以简单的理解为单个内存映射(Memory MApping)的链表(当然实际结构很复杂) 。
里面的每个内存映射(Memory Mapping)都将一块虚拟地址映射到一个特定的地址空间(物理内存或者磁盘存储空间) 。
每个进程拥有自己的页表(Page Table),和其他进程的页表(Page Table)没有关系 。
通过上面的介绍,我们可以简单的将用户进程申请并访问物理内存(或磁盘存储空间)的过程总结如下: