零拷贝原理与实现

什么是零拷贝, 从 Java 到 Netty 零拷贝是指计算机在执行IO操作的时候, CPU不需要将数据从一个存储区复制到另一个存储区, 进而减少上下文切换以及 CPU 拷贝的时间, 这是一种IO操作优化技术零拷贝不是没有拷贝数据, 而是减少用户态, 内核态的切换次数 和 CPU拷贝次数sendfile带有DMA收集拷贝功能的 sendfile。 阅读详情

1.传统拷贝

FileInputStream、FileOutputStream

read:将数据从磁盘读取到内核态缓冲区,再从内核态缓冲区拷贝到用户缓冲区

write:将数据从用户缓冲区写入到socket缓冲区,再从socket缓冲区写入到网卡设备

内核空间:

主要是提供进程调度、内存分配、连接硬件资源等功能

用户空间:

提供给应用程序的空间,不具有访问内核资源的权限。如果用户程序需要使用到内核空间的资源,则需要通过系统调用来完成。进程从用户空间切换到内核空间,完成相关操作后,再从内核空间切换到用户空间。

内核态:

进程运行在内核空间,被称为进程的内核态

用户态:

进程运行在用户空间,被称为进程的用户态。

DMA技术

DMA本质上是一块主板上独立的芯片,允许外设设备和内存存储器之间直接进行IO数据传输,其过程不需要CPU的参与。

主要流程就是:CPU通知DMA将磁盘数据拷贝到内核态后,CPU就可以无需等待执行其他任务。DMA通知磁盘将数据从磁盘放到磁盘缓冲区,磁盘完成后通知DMA,DMA将数据从磁盘缓冲区放到内内核缓冲区中。完成后,通知CPU来取数据。

1.应用程序调用read函数,向操作系统发起IO调用,上下文从用户态切换至内核态
2.DMA控制器把数据从磁盘中读取到内核缓冲区
3.CPU把内核缓冲区数据拷贝到用户应用缓冲区,上下文从内核态切换至用户态,此时read函数返回
4.用户应用进程通过write函数,发起IO调用,上下文从用户态切换至内核态
5.CPU将缓冲区的数据拷贝到socket缓冲区
6.DMA控制器将数据从socket缓冲区拷贝到网卡设备,上下文从内核态切换至用户态,此时write函数返回

 从这里可以看到做一次从磁盘到用户缓冲区的数据提取,需要cpu切换2次,cpu拷贝次数1次,DMA拷贝1次,如果是复制那就需要4次CPU切换,2次CPU拷贝,2次DMA拷贝,所以需要减少CPU在用户态与内核态之间的切换次数以及拷贝次数。

2. 零拷贝

什么是零拷贝?

零拷贝是指计算机执行IO操作时,CPU不需要将数据从一个存储区域复制到另一个存储区域,进而减少上下文切换以及CPU的拷贝时间,是IO操作优化技术。

虚拟内存

虚拟内存远大于物理内存空间。且多个虚拟内存可以映射同一个物理地址。这样当DAM将数据拷贝到内核缓存后,无需cpu将数据再拷贝到用户空间了。

实现零拷贝的方式

1. mmap + write

2. sendfile

3. 带有DMA收集拷贝功能的sendfile

MMAP拷贝 

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

1.用户进程通过调用mmap方法向操作系统内核发起IO调用,上下文从用户态切换至内核态
2.CPU利用DMA控制器,将数据从硬盘拷贝到内核缓冲区
3.上下文从内核态切换回用户态,mmap方法返回
4.用户进程通过调用write方法向操作系统内核再次发起IO调用,上下文从用户态切换至内核态
5.CPU将内核缓冲区的数据拷贝到socket缓冲区
6.CPU利用DMA控制器,将数据从socket缓冲器拷贝到网卡,上下文从内核态切换至用户态,write方法返回

使用mmap + write拷贝,CPU上下文切换4次,拷贝3次(1次CPU拷贝,2次DMA拷贝),由此可见减少了一次CPU拷贝。

sendfile拷贝

sendfile是Linux2.1版本后内核引入 的一个系统调用函数,原型如下

ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

sendfile表示两个文件描述符之间传输数据,他是在操作系统内核中操作的,避免了数据从内核缓冲区和用户缓冲区之际七年的拷贝操作,因此可以用它来实现零拷贝。

1.用户进程发起sendfile系统调用,上下文从用户态切换至内核态
2.DMA控制器将数据从硬盘拷贝到内核缓冲区
3.CPU将读缓冲区中的数据拷贝到socket缓冲区
4.DMA控制器异步把数据从socket缓冲器拷贝到网卡
5.上下文从内核态切换至用户态,sendfile函数返回

使用sendfile拷贝,CPU上下文切换2次,拷贝3次 (1次CPU拷贝,2次DMA拷贝),由此可见减少了两次CPU切换,一次CPU拷贝。

sendfile +DMA scatter/gather实现的零拷贝

1.用户进程发起sendfile系统调用,上下文从用户态切换至内核态
2.DMA控制器将数据从磁盘拷贝到内核缓冲器
3.CPU把内核缓冲区中的文件描述符信息(包括内核缓冲区的内存地址和偏移量)直接发送到socket缓冲区
4.DMA控制器根据文件描述符信息直接把数据从内核缓冲区拷贝到网卡
5.上下文切换至用户态,sendfile返回

sendfile +DMA scatter/gather,只产生2次CPU切换,2次DMA拷贝,这才是真正意义的零拷贝。

拷贝速度对比

Java中拷贝文件的方式

使用文件大小:2657KB

使用FileInputStream、FileOutputStream传统拷贝

private static void fileCopy(){
            FileInputStream fileInputStream = null;
            FileOutputStream fileOutputStream = null;

            try {
                Long t1 = System.currentTimeMillis();
                fileInputStream = new FileInputStream(new File("C:\\Users\\XXX\\IdeaProjects\\text.txt"));
                fileOutputStream = new FileOutputStream(new File("C:\\Users\\XXX\\IdeaProjects\\FileOutputStream.txt"));
                int readData = 0;
                byte[] buf = new byte[1024*1024*10];
                while (-1 != (readData = fileInputStream.read(buf))) {
                    fileOutputStream.write(readData);
                }
                Long t2 = System.currentTimeMillis();
                System.out.println(t2-t1);
            } catch (Exception e) {
                e.printStackTrace();
            }  finally {
                try {
                    fileInputStream.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    fileOutputStream.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

耗时:11

MMAP(FileChannle的read、write)拷贝

private static void mmapCopy() {
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        FileChannel readChannel = null;
        FileChannel wirteChannel = null;

        try {
            Long t1 = System.currentTimeMillis();
            fileInputStream = new FileInputStream(new File("C:\\Users\\xxx\\IdeaProjects\\text.txt"));
            fileOutputStream = new FileOutputStream(new File("C:\\Users\\xxx\\IdeaProjects\\MMAP.txt"));
            readChannel = fileInputStream.getChannel();
            wirteChannel = fileOutputStream.getChannel();
            int n = 0;

            ByteBuffer buf = ByteBuffer.allocate(1024*1024*10);
            while (readChannel.read(buf) != -1) {
                buf.flip();
                wirteChannel.write(buf);
                buf.clear();
                wirteChannel.force(true);
            }

            Long t2 = System.currentTimeMillis();
            System.out.println(t2 - t1);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                readChannel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                wirteChannel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fileInputStream.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fileOutputStream.close();

            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

 耗时:27

sendfile拷贝(FileChannle的transferTo)

private static void senfileCopy() {
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        FileChannel readChannel = null;
        FileChannel wirteChannel = null;

        try {

            fileInputStream = new FileInputStream(new File("C:\\Users\\XXX\\IdeaProjects\\text.txt"));
            fileOutputStream = new FileOutputStream(new File("C:\\Users\\XXX\\IdeaProjects\\SendFile.txt"));
            readChannel = fileInputStream.getChannel();
            wirteChannel = fileOutputStream.getChannel();

            Long t1 = System.currentTimeMillis();
            long len = readChannel.size();
            long position = readChannel.position();
            readChannel.transferTo(position,len,wirteChannel);
            Long t2 = System.currentTimeMillis();
            System.out.println(t2 - t1);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                readChannel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                wirteChannel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fileInputStream.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fileOutputStream.close();

            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

 耗时:3

在小数据量下传统方式和mmap方式没有太大的区别,但是sendFile方式差距还是比较明显的。

传统拷贝mmap+writesendfilesendfile+scatter、gather
CPU切换次数4422
CPU拷贝次数2110
DMA拷贝次数2222
原因存在用户缓冲区和内核缓冲区,使用DMA技术,CPU需要将数据从内核缓冲区到用户缓冲区来回读取增加虚拟内存地址映射,CPU直接通过映射招到内核态的数据copy到Socket缓冲区使用sendfile减少CPU的切换次数使用sendfile减少CPU的切换次数,且CPU不再将数据复制到Socket缓冲区,而是把数据的位置和长度给到Socket缓冲区,由DMA根据位置和长度直接从内核缓冲区复制到磁盘
系统调用read/writemmap/writesenfilesendfile+scatter/gather

零拷贝(Zero-Copy) 零拷贝并不是指在数据的传输过程中发生拷贝的次数为零,而是指数据在传输过程中从内核空间到用户空间之间的数据拷贝次数为零。通过减少数据在用户空间和内核空间之间的复制次数,零拷贝技术可以极大地提升I/O的性能,尤其是在大文件传输、网络通信等场景中具有显著的优势。 阅读详情

相关推荐

零拷贝Zero Copy

零拷贝技术指在计算机执行操作的时候,CPU不需要先将数据从一个内存区域复制到另一个内存区域,从而和,实现CPU的零参与,彻底消除CPU在这方面的负载实现零拷贝的主要技术是技术和技术。

2302_80742310的博客 1283

零拷贝(Zero Copy)

零拷贝技术指的是在计算机执行操作时,CPU不需要先将数据从一个内存区域复制到另一个内存区域,从而可以减少上下文以及CPU的拷贝时间。他的作用是在数据报从网络设备到用户程序空间传递的过程,减少数据拷贝的次数,减少系统调用,实现CPU的零参与,彻底消除CPU在这方面的负载,实现零拷贝的最主要的技术就是DMA数据传输技术和内存区域映射技术。零拷贝就是可以减少数据在用户缓冲区和内核缓冲区之间的反复的I/O拷贝操作。零拷贝机制可以减少用户进程地址空间和内核地址空间之间因为上下文切换带来的CPU开销。

m0_62645012的博客 8288

【Arduino】入门篇——交通信号灯

模拟交通信号灯一、实验目的二、实验材料三、电路图四、实验过程五、代码块六、实验结果 一、实验目的 我想大家都看见过交通灯,就是马路上十字路口的红绿灯。如果您开过车,我想您一定仔细观察过交通灯,如果您还没有驾驶过车,您是否仔细观察过交通灯呢?交通灯包括三种个不同颜色的灯:红灯、黄灯和绿灯。 每个路口的红绿灯切换的时间并不是相同,这个是根据不同路口的车流情况来设定的,下面就是模仿交通灯的一个实验 二...

漠宸离若的博客 1万+

零拷贝(Zero Copy)技术

零拷贝技术简述

qq_35630121的博客 3307

开源分享:苹果群控手机源代码解析与实战

本文介绍了苹果设备群控的基本原理和实现方法,重点解析了基于Python+Appium的群控系统构建。主要内容包括:1)设备连接管理技术(USB/Wi-Fi);2)自动化控制方式(WDA/AppleScript/Appium);3)实战演示了通过Python脚本实现多设备同时控制,涵盖环境配置、代码解析和功能说明;4)提出了多线程、图像识别等优化方向。文章为开发者提供了快速上手的群控方案,适用于自动化测试、批量管理等场景,并推荐了相关开源项目参考。

2403_88540309的博客 1344

01-SA8155P 冷启动强制进入EDL模式

冷启动EDL模式

静虚待令,有物混成 3088

零拷贝:原理与实现

I/O 或输入/输出通常意味着CPU) 与如磁盘、鼠标、键盘等)之间的读写。在深入研究零拷贝之前,有必要指出包括磁盘设备和其他块导向设备)和之间的区别。。同时,。套接字接口背后发生的事情是发送方和接收方计算机创建自己的套接字,并设置发送或接收文件的连接。如今,越来越多的 Web 应用程序已经实现了从 CPU 绑定到 I/O 绑定的转变,这意味着 I/O 的性能通常是这些应用程序的瓶颈。。数据必须,而。这时零拷贝就派上用场了。零拷贝的主要原理是尽可能地消除或。

在技术的广袤天地里,本博客如精准罗盘。剖析前沿科技,深掘代码奥秘,以精炼笔触,带您穿越复杂技术迷宫,速达知识彼岸。 1412

Ubuntu20.04安装Torque-6.1.2单机版(踩坑篇)

说明:PBS排队系统原先是在Centos7安装使用很顺利,但是有客户需求在Ubuntu20.04上使用,着手在Ubuntu20.04安装上安装的时候发现很多报错,并不能顺利安装,网上查找到的教程,有的说是让放弃转slurm,有的是换源安装,但是安装好的版本很低,有许多bug,不是很好用。经过自己慢慢摸索之后,改了部分配置以及源码之后,能够顺利安装,再次记录一下踩坑心得,与大家一起分享学习。如有问题,欢迎大家来撩。...............

华青水上的博客 8087

Netty实现的零拷贝:原理、源码与实践

摘要: Netty通过零拷贝技术优化数据传输效率,减少CPU和内存开销。其实现分为操作系统层面和用户空间层面:1)操作系统层面利用sendfile机制,通过FileRegion和transferTo直接传输文件数据,避免用户空间拷贝,支持SG-DMA时实现完全零拷贝;2)用户空间层面通过CompositeByteBuf虚拟聚合多个ByteBuf,逻辑连续访问并零拷贝写入网络,减少内存复制。两种方式分别针对大文件传输和多段数据聚合场景,显著降低CPU占用、内存带宽压力及传输延迟,适用于高并发和低延迟应用。

持续输出Java相关知识 1018

在Qt中集成VTK和PCL:实现数据可视化的完整指南

在现代软件开发中,数据可视化至关重要。将VTK(Visualization Toolkit)和PCL(Point Cloud Library)集成到Qt环境里,能为开发者提供强大的可视化解决方案。本文将深入讲解如何在Qt中读取PCL文件,展示VTK模型和PCL数据,适合想要在Qt项目中实现数据可视化的开发者。

轩宇的博客 916

LVGL 实战:倒计时翻页钟

环境:LVGL 9.x + PC 模拟器。每个数字做成上下两半的卡片,秒变时用绕中缝翻页:上半旧页折叠下去、下半新页展开上来,配合阴影遮罩做出立体感。从 02:00 倒计时到 0,闪一下再重置。界面文案用英文(默认字体无中文)。

摸鱼专家 211

零拷贝的实现原理

参考:蚂蚁二面,面试官问我零拷贝的实现原理,当场懵了…

了凡的博客 333

Python爬虫实战:模拟登录B站 – 处理Cookie和加密参数

由于B站在登录过程中采用了多种安全措施,包括加密的请求参数和cookie验证,模拟登录成为一项具有挑战性的任务。首先,我们需要获取B站的登录页面,并解析出其中的CSRF令牌和其他隐藏的字段。B站的登录接口通常会包含一些动态的加密参数,我们需要在登录前通过GET请求获取这些信息。本文详细介绍了如何使用Python模拟登录B站,解决加密参数的处理、图形验证码的识别以及登录后的数据抓取。库中的加密方法加密登录请求中的密码。一旦登录成功,我们可以通过维护会话状态,抓取登录后的数据,如个人主页、评论、观看记录等。

2201_76125261的博客 1309

【转】零拷贝的实现原理

原文:蚂蚁二面,面试官问我零拷贝的实现原理,当场懵了… 架构师社区以下文章来源于占小狼的博客,作者占小狼 链接:https://mp.weixin.qq.com/s/xA5irZwZL-ryw0qwVZXi8Q Table of Contents 具体过程: 相关文章 "狼哥,面试又跪了,碰到了知识盲区" "哪个?" "一面还可以,二面面试官问我零拷贝的原理,懵逼了...这块内...

RToax 1087

IMX6ULL---从零开始移植uboot-imx

IMX6ULL---从零开始移植uboot-imx

weixin_42162924的博客 1028

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

零拷贝实现原理与使用

若有收获,请记得分享和转发哦零拷贝是中间件相关面试中必考题,本文就和大家一起来总结一下NIO拷贝的原理,并结合Netty代码,从代码实现层面近距离观摩如何使用java实现零拷贝。1、零拷贝...

IT技术精选文摘 287

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

零拷贝原理和java实现

转载链接:https://www.jianshu.com/p/497e7640b57c 什么是零拷贝 WIKI中对其有如下定义: "Zero-copy" describes computer operations in which the CPU does not perform the task of copying data from one memory area to another. ...

qq_35986946的博客 529

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

(转载)零拷贝的原理及Java实现

在谈论Kafka高性能时不得不提到零拷贝。Kafka通过采用零拷贝大大提供了应用性能,减少了内核和用户模式之间的上下文切换次数。那么什么是零拷贝,如何实现零拷贝呢? 什么是零拷贝? WIKI中对其有如下定义: "Zero-copy" describes computer operations in which the CPU does not perform the task of copying data from one memory area to another. 从WIKI的定义中,

Dream_it_possible!的博客 821

深入剖析Linux IO原理和几种零拷贝机制的实现

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

陌上轩客 1194

Netty零拷贝的实现原理

零拷贝的应用程序要求内核(kernel)直接将数据从磁盘文件拷贝到套接字(Socket),而无须通过应用程序。零拷贝不仅提高了应用程序的性能,而且减少了内核和用户模式见上下文切换。 1.传统方法 从文件中读取数据,并将数据传输到网络上的另一个程序的场景:从下图可以看出,拷贝的操作需要4次用户模式和内核模式之间的上下文切换,而且在操作完成前数据被复制了4次。 从磁盘中copy放到一个内存buf中,然后将buf通过socket传输给用户,下面是伪代码实现: read(file, tm...

傅红雪的专栏 1014

零拷贝原理以及java中实现方式和使用场景

零拷贝技术通过减少数据在用户空间和内核空间之间的复制次数,极大地提升了 I/O 的性能,特别是在大文件传输、网络通信等场景中具有显著的优势。Java 提供的mmap等 API,以及第三方网络框架(如 Netty)的支持,使得零拷贝技术能够被轻松应用于高性能 I/O 应用中。

yymagicer的博客 1869

Linux 零拷贝技术:原理、实现与应用场景

Linux 零拷贝技术:原理、实现与应用场景

2401_85199775的博客 1656

零拷贝原理及实现

什么是零拷贝?零是指拷贝的次数为零,拷贝是指数据从一个存储区域转移到另一个存储区域,所以零拷贝就是指不需要将数据从一个存储区域复制到另一个存储区域,即 计算机在执行IO操作时,CPU不需要从一个存储区域复制到另一个存储区域,进而减少上下文切换以及CPU的拷贝时间。它是一种IO操作优化技术。可以看到,整个数据的传输过程,都要需要 CPU 亲自参与搬运数据的过程,而且这个过程,CPU 是不能做其他事情的。

m0_63435402的博客 2830

面试官问我零拷贝的实现原理,当场懵 了

"哥,面试又跪了,碰到了知识盲区" "哪个?" "一面还可以,二面面试官问我零拷贝的原理,懵逼了...这块内容没去研究过" "哦,这个知识点,我之前应该有讲过,你没注意到?" "这东西工作中用不到,可能被我忽略了" "啧啧啧..." "哎,有空和我讲讲?" "先从简单开始,实现下这个场景:从一个文件中读出数据并将数据传到另一台服务器上?" "为啥写这个?" "你先写" "行..." 1分钟后 "我写了伪代码" "这里涉及到了几次数据拷贝?" "2次?磁盘拷贝到内存,内存.

芒果不是程序猿v: 的博客 215
上一篇: 线程池ThreadPoolExecutor
下一篇: Kylin 构建Cube报错(“com.mysql.jdbc.Driver“) was not found in the CLASSPATH
fox_初始化
博客等级 码龄10年 53粉丝 62原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值