零拷贝是什么_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)


相关推荐

  • (20211206更新)ubuntu18.04 安装Python3.8.3、jupyter notebook远程连接配置、虚拟环境搭建。及torch、tensorflow成功下载[通俗易懂]

    (20211206更新)ubuntu18.04 安装Python3.8.3、jupyter notebook远程连接配置、虚拟环境搭建。及torch、tensorflow成功下载[通俗易懂]最近搞了一个低配云服务器,就瞎整。多次踩坑后,进行记录问题之前有试过删除软链接、进行替换#删除软连接sudorm-rf/usr/bin/python3sudorm-rf/usr/bin/pip3#新建软连接sudoln-s/usr/local/python3/bin/python3.8/usr/bin/python3sudoln-s/usr/local/python3/bin/pip3.8/usr/bin/pip3但是吧,后续的pipinstall会出

  • 内网安全 信息收集(收集内网计算机的所有信息 进行攻击.)

    内网安全 信息收集(收集内网计算机的所有信息 进行攻击.)?“信息收集”会对渗透测试工程师和网络安全工程师具有重大作用:???在渗透测试人员进入一个内网后,面对的是一片“未知的区域”,所以渗透测试人员首先会对当前所处的网络环境进行判断,通常的判断分为三种.?(1)我是谁?——对计算机的角色进行判断.?(2)我在哪?——对目前机器所处位置区域的判断。?(3)这是哪?——对目前机器所处网络环境的拓扑结构进行分析和判断。

  • pytest的assert_java断言assert

    pytest的assert_java断言assert前言断言是写自动化测试基本最重要的一步,一个用例没有断言,就失去了自动化测试的意义了。什么是断言呢?简单来讲就是实际结果和期望结果去对比,符合预期那就测试pass,不符合预期那就测试failed

  • 用bootstrap模态框的时候,点击多少次按钮(确定、关闭),后台提交多少次Ajax,重复提交…

    用bootstrap模态框的时候,点击多少次按钮(确定、关闭),后台提交多少次Ajax,重复提交…

  • Python+selenium 自动化-chrome驱动的下载安装

    Python+selenium 自动化-chrome驱动的下载安装chrome驱动下载chrome驱动获取:chromedriver.storage.proxy.ustclug.org如何查看对应浏览器版本的驱动:不同的版本的驱动支持不同版本的浏览器,所以版本一定要对应好。首先找到一个版本打开来,下面有个notes,这个就可以查看部分版本支持。chrome驱动安装直接解压到Python的根目录下即可。…

  • 大数据应用开发八大基本原则

    大数据应用开发八大基本原则·        大数据应用正在从概念走向现实,而企业在大数据应用开发时,软件的弹性(Resilient)正在成为决定大数据应用成败的关键因素。弹性差的应用无法应对大规模的数据集,在测试和运营中也缺乏透明度,而且也不安全。·        避免大数据应用在生产环境中掉链子的最佳办法就是在开发阶段就开发弹性应用,例如:健壮性、经过测试、可改变、可审计、高安全、可监控。·        可以说

发表回复

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

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