零拷贝是什么_file.copy()

零拷贝是什么_file.copy()一、DMAio读写有两种方式:中断 DMA用户进程发起数据读取请求 系统调度为该进程分配cpu cpu向io控制器(ide,scsi)发送io请求 用户进程等待io完成,让出cpu 系统调度cpu执行其他任务 数据写入至io控制器的缓冲寄存器 缓冲寄存器满了向cpu发出中断信号 cpu读取数据至内存通过中断,cpu需要拷贝数据。2、DMA用户进程发起…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

一、DMA

io读写有两种方式:

  • 中断
  • DMA

零拷贝是什么_file.copy()

  1. 用户进程发起数据读取请求
  2. 系统调度为该进程分配cpu
  3. cpu向io控制器(ide,scsi)发送io请求
  4. 用户进程等待io完成,让出cpu
  5. 系统调度cpu执行其他任务
  6. 数据写入至io控制器的缓冲寄存器
  7. 缓冲寄存器满了向cpu发出中断信号
  8. cpu读取数据至内存

通过中断,cpu需要拷贝数据。

2、DMA

零拷贝是什么_file.copy()

  1. 用户进程发起数据读取请求
  2. 系统调度为该进程分配cpu
  3. cpu向DMA发送io请求
  4. 用户进程等待io完成,让出cpu
  5. 系统调度cpu执行其他任务
  6. 数据写入至io控制器的缓冲寄存器
  7. DMA不断获取缓冲寄存器中的数据(需要cpu时钟)
  8. 传输至内存(需要cpu时钟)
  9. 所需的全部数据获取完毕后向cpu发出中断信号

减少cpu中断,不用cpu拷贝数据,把数据拷贝这类工作从cpu中解放出来。

二、数据传输1

在一个web系统中从一个文件中读出数据并将数据传输到网络上另一程序的场景,有两种方式:

1、传统方式:

读取数据后并通过网络发送 所发生的数据拷贝,java代码如下:

File.read(fileDesc, buf, len);
Socket.send(socket, buf, len);

这里主要使用了linux底层的read()和write()两个系统调用,整个流程如下图:

零拷贝是什么_file.copy()

  • 一个read系统调用后,DMA执行了一次数据拷贝,从磁盘到内核空间
  • read结束后,发生第二次数据拷贝,由cpu将数据从内核空间拷贝至用户空间
  • send系统调用,cpu发生第三次数据拷贝,由cpu将数据从用户空间拷贝至内核空间(socket缓冲区)
  • send系统调用结束后,DMA执行第四次数据拷贝,将数据从内核拷贝至协议引擎

整个过程有四次数据拷贝,并且每个过程都发生一次上下文切换。

2、sendfile(零拷贝):

上面的方式我们没有对文件内容做任何修改,那么在内核空间和用户空间来回拷贝数据无疑就是一种浪费,而零拷贝主要就是为了解决这种低效性。java代码如下:

transferTo(position, count, writableChannel);

这里主要依赖linux底层sendfile()调用。Linux 2.1 版本提供了sendfile函数,其基本原理如下:数据根本不经过用户态,直接从内核缓冲区进入到 Socket Buffer。流程如下:

零拷贝是什么_file.copy()

  • DMA从拷贝至内核缓冲区
  • cpu将数据从内核缓冲区拷贝至内核空间(socket缓冲区)
  • DMA将数据从内核拷贝至协议引擎

这三个过程中共发生三次数据拷贝,2次上下文切换,分别为发起读取文件和发送数据。

3、进一步优化:

上面的方式尚未达到我们的零拷贝要求。如果底层网络接口卡支持收集操作 的话,那么我们就可以进一步减少内核的数据复制。在 Linux 内核 2.4 及后期版本中,套接字缓冲区描述符就做了相应调整,以满足该需求。这种方法不仅可以减少多个上下文切换,还可以消除需要涉及 CPU 的重复的数据拷贝。对于用户方面,用法还是一样的,整个流程如下:

零拷贝是什么_file.copy()

  • MA从拷贝至内核缓冲区
  • 将数据的位置和长度的信息的描述符增加至内核空间(socket缓冲区)
  • DMA将数据从内核拷贝至协议引擎

整个过程共发生两次数据拷贝。

参考:

https://www.ibm.com/developerworks/cn/java/j-zerocopy/

https://www.cnblogs.com/z-sm/p/6547709.html

https://blog.csdn.net/xiaofei0859/article/details/74321216

https://www.cnblogs.com/stateis0/p/10960579.html

java零拷贝示例代码:

1、文件到文件:

class ZerocopyFile {
    @SuppressWarnings("resource")
    public static void transferToDemo(String from, String to) throws IOException {
        FileChannel fromChannel = new RandomAccessFile(from, "rw").getChannel();
        FileChannel toChannel = new RandomAccessFile(to, "rw").getChannel();

        long position = 0;
        long count = fromChannel.size();

        fromChannel.transferTo(position, count, toChannel);

        fromChannel.close();
        toChannel.close();
    }

    @SuppressWarnings("resource")
    public static void transferFromDemo(String from, String to) throws IOException {
        FileChannel fromChannel = new FileInputStream(from).getChannel();
        FileChannel toChannel = new FileOutputStream(to).getChannel();

        long position = 0;
        long count = fromChannel.size();

        toChannel.transferFrom(fromChannel, position, count);

        fromChannel.close();
        toChannel.close();
    }

    public static void main(String[] args) throws IOException {
        String from = "src/main/java/zerocopy/1.data";
        String to = "src/main/java/zerocopy/2.data";
        // transferToDemo(from,to);
        transferFromDemo(from, to);
    }
}

2、socket:

/**
 * disk-nic零拷贝
 */
class ZerocopyServer {
    ServerSocketChannel listener = null;

    protected void mySetup() {
        InetSocketAddress listenAddr = new InetSocketAddress(9026);

        try {
            listener = ServerSocketChannel.open();
            ServerSocket ss = listener.socket();
            ss.setReuseAddress(true);
            ss.bind(listenAddr);
            System.out.println("监听的端口:" + listenAddr.toString());
        } catch (IOException e) {
            System.out.println("端口绑定失败 : " + listenAddr.toString() + " 端口可能已经被使用,出错原因: " + e.getMessage());
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        ZerocopyServer dns = new ZerocopyServer();
        dns.mySetup();
        dns.readData();
    }

    private void readData() {
        ByteBuffer dst = ByteBuffer.allocate(4096);
        try {
            while (true) {
                SocketChannel conn = listener.accept();
                System.out.println("创建的连接: " + conn);
                conn.configureBlocking(true);
                int nread = 0;
                while (nread != -1) {
                    try {
                        nread = conn.read(dst);
                    } catch (IOException e) {
                        e.printStackTrace();
                        nread = -1;
                    }
                    dst.rewind();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class ZerocopyClient {
    public static void main(String[] args) throws IOException {
        ZerocopyClient sfc = new ZerocopyClient();
        sfc.testSendfile();
    }

    public void testSendfile() throws IOException {
        String host = "localhost";
        int port = 9026;
        SocketAddress sad = new InetSocketAddress(host, port);
        SocketChannel sc = SocketChannel.open();
        sc.connect(sad);
        sc.configureBlocking(true);

        String fname = "src/main/java/zerocopy/test.data";
        FileChannel fc = new FileInputStream(fname).getChannel();
        long start = System.nanoTime();
        long nsent = 0, curnset = 0;
        curnset = fc.transferTo(0, fc.size(), sc);
        System.out.println("发送的总字节数:" + curnset + " 耗时(ns):" + (System.nanoTime() - start));
        try {
            sc.close();
            fc.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }
}

三、数据传输2

还有一个零拷贝的例子mmap。传统方式使用read、write进行文件会产生用户态和内核态数据的拷贝,使用mmap,将文件映射到内核缓冲区,同时,用户空间可以共享内核空间的数据。

这里只做一个介绍,具体mmap的原理、使用下次再说。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/191106.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 动态规划背包问题

    动态规划背包问题一、0-1背包1.      有n个重量和价值分别为wi,vi的物品。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值。(1<=n<=100,1<=wi,vi<=100,1<=W<=10000)样例输入:4231234225 42133457910样例输出…

  • pytest指定用例_文件夹排列顺序自定义

    pytest指定用例_文件夹排列顺序自定义前言测试用例在设计的时候,我们一般要求不要有先后顺序,用例是可以打乱了执行的,这样才能达到测试的效果.有些同学在写用例的时候,用例写了先后顺序,有先后顺序后,后面还会有新的问题(如:上个用例返回

  • 直方图均衡化(Matlab实现)

    直方图均衡化(Matlab实现)直方图均衡化定义:通过某种灰度映射使输入图像转换为在每一灰度级上都有近似相同的像素点的输出图像(即输出的直方图是均匀的)。Matlab图像处理工具箱提供了用于直方图均衡化的函数histeq(),调用语法如下:[J,T]=histeq(I)I是原始图像,J是经过直方图均衡化的输出图像,T是变换矩阵图像归一化:将图像转换成唯一的标准形式以抵抗各种变换,从而可消除同类图像不同变形体之间的外观差异灰度归一…

    2022年10月21日
  • 单片机控制步进电机正反转c语言程序,单片机控制步进电机1步10步100步正反转…

    单片机控制步进电机正反转c语言程序,单片机控制步进电机1步10步100步正反转…原标题:单片机控制步进电机1步10步100步正反转一,程序设计方案的构想:1)的控制原理步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件.在非超载的情况下,电机的转速,停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响.即给电机加一个信号,电机则转过一个步距角.这一线形关系的存在,加上步进电机只有周期性的误差而无积累误差等特点,使得在线速度,位置等控制领域用步进电机来控制变的…

  • 怎么修改HTML网页的名字_如何修改html文件内容

    怎么修改HTML网页的名字_如何修改html文件内容NetCms默认设置中,只能上传Doc文件,不能上传xls文件和PPT文件。 上传文件类型可以“控制面板–>参数设置–>上传文件允许格式”中设置。但是,仅能上传,添加新闻时,添加附件的文件选择框中无法看到xls文件和ppt文件。 通过查看源文件,添加新闻页面是~/Manage/News/News_add.aspx文件,在该文件中,添加附件位置,通过调用JavaScript的s

  • java多线程中的join方法详解[通俗易懂]

    java多线程中的join方法详解[通俗易懂]java多线程中的join方法详解 方法Join是干啥用的?简单回答,同步,如何同步?怎么实现的?下面将逐个回答。   自从接触Java多线程,一直对Join理解不了。JDK是这样说的:joinpublicfinalvoidjoin(longmillis)throwsInterruptedExceptionWaitsatmostmillismi

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号