Wiki对零拷贝的定义

"Zero-copy" describes computer operations in which the CPU does not perform the task of copying data from one memory area to another.

零拷贝(Zero-copy)是指在计算机执行操作时,CPU 不需要将数据从一块内存拷贝到另一块内存,减少拷贝次数可以提高性能。

在操作系统层面来说零拷贝是指不需要将数据从内核空间复制到用户空间,而Netty、Kafka等框架都因零拷贝而闻名著称,技术来不得半点马虎和一知半解,本着知其然知其所以然的态度,本系列为你揭秘其中原委和解决方案。

计算机组成

计算机是由硬件、内核和上层应用组成,通过它们在功能上由下而上的层层传递给用户提供各种服务,如下图所示。为了便于独立开发、调试和维护,采用了高内聚低耦合分层设计思想:内核负责对硬件直接操作,在封装硬件操作的同时给上层应用提供功能接口,承上启下;上层应用调用内核接口为用户提供业务服务。每一层都使用较低层提供的功能而不必知道其实现细节,只需了解其接口能做什么即可。

实际上随着时间的演进和功能的不断丰富,内核体积变得庞大不易管理,所以现代的操作系统基本都采用微内核的设计思想:把内核模块化,将非基础模块从内核中移除,把这些非基础模块实现为系统应用,甚至用户应用,从而减少内核的体积和复杂度,使其功能更聚焦。

微内核设计的好处颇多:

  1. 方便扩展内核,所有新的应用都可以在用户空间增加而不必修改内核;
  2. 由于大多数应用都是作为用户进程而非内核进程来运行的,为微内核提供了更好的安全性和可靠性;
  3. 微内核较小,开发、调试和维护工作量都相对较少,而且容易进行硬件平台移植;

然而微内核究竟包括哪些基础模块,实际上每个操作系统的处理并不相同,并没有定论和标准,但一般至少会包括进程、内存管理和通讯功能。

上层应用包含了系统应用和用户应用:系统应用一般跟随系统发行版而来,但也是通过调用内核接口开发的,一般是用于系统管理;用户应用是用户自行开发的应用,一般是为了实现自己的业务逻辑。但上层应用一般都采用高级语言来编写,为了降低复杂性和高效,高级语言对内核接口进行了封装,提供了编程语言类库,比如C语言的标准库、Java的JDK等。

用户空间和内核空间

用户进程不能直接操作硬件,只有通过内核提供的接口来操作,而为了确保内核的正常、安全地运行,不会因上层应用的异常导致内核陷入灾难,就必须区分内核代码执行和用户定义代码执行,也就是所谓的双重模式即:内核态和用户态。当用户程序正在执行,系统处于用户态,当用户程序需要调用内核功能,它必须通过系统调用的形式转换为内核态执行。一般是通过硬件支持来区分两种模式的,在硬件中增加了一个模式bit位:0代表内核态,1代表用户态。

系统通过引导程序,装入内核处于内核态,紧接着开始执行用户进程进入用户态(模式位为1),一旦遇到中断或系统调用,则又从用户态进入内核态(模式位为0),内核处理完后返回用户进程进入用户态(模式位为1),如上图。

进程是操作系统资源分配的最小单元,进程在执行上有用户态和内核态,那么虚拟内存也分为了用户空间和内核空间,供用户态和内核态的进程使用。比如32位的操作系统内存可以高达4G,把最高的1G字节(虚拟内存地址0xC0000000~0xFFFFFFFF)供内核使用,称为内核空间,而将较低的3G字节(虚拟内存地址 从0x00000000到0xBFFFFFFF)供上层应用使用,称为用户空间。

虚拟内存是相对于物理内存而言,操作系统会对物理内存进行映射和抽象,软件的所有操作都是对虚拟内存而言,也可以理解为物理内存映射为用户空间和内核空间。

当进程由用户态进行进入内核态,系统需要保存当前运行在CPU中进程的上下文,从而能在其处理完毕后转换为用户态时能恢复其上下文,这一任务称为上下文切换(context switch)。上下文切换在计算机执行期间会比较频繁,只要牵涉到内核态和用户态的转换就会涉及到上下文切换。所谓的上下文究竟是指什么呢?上下文从其英文context可知,是进行运行的环境,它包括进程的状态、计数器、全局变量、临时数据如函数参数、返回地址、局部变量等,还可能包括运行期间动态分配的内存堆(heap)。频繁的上下文切换,对数据的保存和恢复操作过于频繁,对性能的影响特别显著。

示例

为了全面理解用户空间、内核空间、用户态、内核态,我们举个例子来说明:读取文件内容并通过Socket发送。

由于用户进程无法直接操作硬件,因此用户进程首先需要通过系统调用(System Call)来调用内核接口,此时的事件流如下

  1. 用户进程通过系统调用读取文件内容,由用户态进入内核态;
  2. 内核通过直接内存(DMA)的方式获取文件内容,并返回用户进程,由内核态转换用户态;
  3. 用户进程对数据进行处理后,通过系统调用Socket发送数据,由用户态进入内核态;
  4. 内核通过直接内存(DMA)的方式发送数据,并返回用户态;

由上图流程可知会经历4次上下文切换,而它的数据会也经历了4次拷贝,数据流向如下

  1. 内核通过DMA方式,把文件内容拷贝到内核空间;
  2. 从内核空间通过CPU拷贝到用户空间,供用户进程使用;
  3. 用户处理完毕后,把数据从用户空间通过CPU拷贝到内核空间;
  4. 内核通过DMA方式拷贝到网卡发送;

什么是DMA

所有的硬件是通过控制器连接到计算机总总线,传统的中断式I/O方式是把数据拷贝到控制器寄存器,控制器再以中断的方式通知CPU拷贝到内存。由于这种方式频繁的中断,导致大量占用CPU时间片。DMA是Direct Memory Access的缩写,中文称之为直接存储器访问。它的使用方式是CPU通知DMA控制器进行I/O后CPU就被解脱出来做别的事情了,数据的拷贝过程都是由DMA来操作完成,数据拷贝完成后DMA控制器以中断的方式通知CPU。

写在最后

本篇我们了解了用户态、内核态、用户空间、内核空间的概念,而且从事件流和数据流我们也找到了提高性能的优化方向:降低拷贝和上下文切换次数,下一篇我们将揭晓优化方案。

相关阅读


缓存穿透、缓存击穿、缓存雪崩看这篇就够了

一口气讲透一致性哈希(Hash),助力「码农变身」

漫画 | 架构设计中的那些事

Java中异常处理的9个最佳实践

Intellij IDEA必备插件,提高效率的“七种武器”

接住喽,送你个装B的技能:JDK动态代理

给“小白”漫画+图示讲解MyBatis原理,就问香不香

除零中断是什么意思?_百万并发「零拷贝」技术系列之初探门径相关推荐

  1. php零拷贝,百万并发「零拷贝」技术系列之初探门径

    Wiki对零拷贝的定义 "Zero-copy" describes computer operations in which the CPU does not perform th ...

  2. 多维数组的索引与切片_「GCTT 出品」Go 系列教程——11. 数组和切片

    Go语言中文网,致力于每日分享编码知识,欢迎关注我,会有意想不到的收获! Go 系列教程是非常棒的一套初学者教程,入门就它了. 「GCTT 出品」Go 系列教程--1. 介绍与安装 「GCTT 出品」 ...

  3. go 修改结构体方法_「GCTT 出品」Go 系列教程——26. 结构体取代类

    Go语言中文网,致力于每日分享编码.开源等知识,欢迎关注我,会有意想不到的收获! Go 支持面向对象吗? Go 并不是完全面向对象的编程语言.Go 官网的 FAQ 回答了 Go 是否是面向对象语言,摘 ...

  4. go 自定义error怎么判断是否相等_「GCTT 出品」Go 系列教程——30. 错误处理

    Go语言中文网,致力于每日分享编码.开源等知识,欢迎关注我,会有意想不到的收获! Go 系列教程是非常棒的一套初学者教程,入门就它了. 这是 Golang 系列教程中的第 30 篇.在本章教程中,我们 ...

  5. Java并发压力测试数据库_百万并发压力测试-如何用Java编写纯并发压力测试

    进口: 进口: 进口: 进口: 进口: 进口: 进口: 进口: 进口: 进口: 公共阶级{并发测试与压力测试. 私有静态int thread_num=200: 私有静态int client_num=4 ...

  6. 上海内推 | 极氪智能科技百万年薪「氪学家」项目招聘规控/感知算法工程师

    合适的工作难找?最新的招聘信息也不知道? AI 求职为大家精选人工智能领域最新鲜的招聘信息,助你先人一步投递,快人一步入职! 极氪智能科技 「氪学家」是极氪智能科技倾斜极氪战略规划与资源,用百万年薪吸 ...

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

    " 零拷贝(Zero-copy)技术指在计算机执行操作时,CPU 不需要先将数据从一个内存区域复制到另一个内存区域,从而可以减少上下文切换以及 CPU 的拷贝时间. 图片来自 Pexels ...

  8. 零中频接收机频率转换图_复数RF混频器零中频架构及高级算法:下一代SDR收发器中的黑魔法...

    RF工程常被视为电子领域的黑魔法.它可能是数学和力学的某种奇特组合,有时甚至仅仅是试错.它让许多优秀的工程师不得其解,有些工程师仅了解结果而对细节毫无所知.现有的许多文献往往不建立基本概念,而是直接跳 ...

  9. 零基础学python语言_致初学者:零基础如何学好,Python这门编程语言?

    前言 对于很多Python这门编程语言的初学者,往往会面临以下问题: Python2和Python3我该学习哪一个? 是否要安装Linux系统学习Python? Python3有各种版本我该安装哪一个 ...

最新文章

  1. 分享Kali Linux 2016.2第50周镜像文件
  2. php实现 明明的随机数
  3. 隔行换色案例||全选和全不选||QQ表情选择||多选下拉列表左右移动
  4. 独家下载!《零售数据中台通关指南》,带你玩转新零售
  5. Java中MySQL事务处理举例
  6. Python冒泡排序(4)
  7. android gridvie item,Android开发―解决自定义GridView高度第一个item高度异常问题
  8. LeetCode 852 Peak Index in a Mountain Array 解题报告
  9. 手机黑圆点怎么打_输入法:外国人名字中间的点(实心小黑点)怎么打出来?...
  10. Golang publish module
  11. js删除节点的坑(删不完),以li为列
  12. 丽思卡尔顿游轮正式加入万豪旅享家旅行计划
  13. 两轮电动车被小米、哈啰们盯上了
  14. Delphi 基本算法
  15. VS Code 常用快捷键代码大全
  16. 一辈子不用考试?你可能是个假程序员
  17. idea报错Cannot run program tomcat的catalina.bat文件或windows无法找到bat文件
  18. NMEA1803协议3.0版本及以上说明
  19. iphone手机上卸载非主界面上的软件
  20. GUI(用户图形界面)

热门文章

  1. 图像语义分割:U-Net网络和PSP网络
  2. python——LeetCode刷题
  3. curl怎么输出赋值_python怎么实现循环
  4. mysql中的count函数和sum函数如果条件不符合返回什么
  5. 《移动项目实践》实验报告——Android初级控件
  6. LeetCode175 组合两个表
  7. 青岛农业大学第九届ACM程序设计竞赛
  8. 【学习笔记】rabbitmq设置队列ttl和使用延迟插件的代码示例
  9. ArcGis【基本使用】
  10. 【CentOS Linux 7】实验2【Linux多用户管理】