Java NIO-09-零拷贝之 DMA
DMA 的好处
在介绍DMA之前我想问大家:我们为什么要引入DMA,DMA对我们有什么好处那?
计算机系统中各种常用的数据输入/输出方法有查询方式(包括无条件及条件传送方式)和中断方式,这些方式适用于CPU与慢速及中速外设之间的数据交换。
但当高速外设要与系统内存或者要在系统内存的不同区域之间进行大量数据的快速传送时,就在一定程度上限制了数据传送的速率。
直接存储器存取(DMA)就是为解决这个问题提出的,采用DMA方式,在一定时间段内,由DMA控制器取代CPU,获得总线控制权,来实现内存与外设或者内存的不同区域之间大量数据的快速传送。
同时很重要的一点是当DMA传输数据时,并不占用CPU资源,在这个时候CPU可以空出手来做其他的事情。
这样我们既可以做大量数据的高速传输又可以让CPU有时间和资源去做其他的事情。
DMA 芯片的实现
上面介绍了什么是DMA,也介绍了DMA的重要性。那么我们就要看看我们芯片中的DMA了。
在S3C2440A中,我们集成了DMA模块,可以用来传递高速传输数据。既然是数据传输那么我又要问了,我们知道数据传输三要素:源,目的,长度。这是我们数据传输时要知道的。那么在S3C2440A中,源,目的,长度是怎么表示的那?
ps: 硬件知识,暂时不做研究。
DMA映射
基本原理
DMA映射主要为在设备与主存之间建立DMA数据传输通道时,在主存中为该DMA通道分配内存空间的行为,该内存空间也称为DMA缓冲区。
这个任务原本可以很简单,但是由于现代处理器cache的存在,使得事情变得复杂。
RAM与cache内容的一致性问题
出现问题原因
现代处理器为了提升系统性能,在CPU与RAM之间加入了高速缓存cache,所以当在RAM中为一个DMA通道建立一段缓冲区时,必须仔细考虑RAM与cache内容的一致性问题。
具体分析
如果RAM与Device之间的一次数据交换改变了RAM中DMA缓冲区的内容,而cache中缓存了DMA缓冲区对应的RAM中一段内存块。
如果没有机制保护cache中的内容被新的DMA缓冲区数据更新(或者无效),那么cache和他对应的RAM中的一段内存块在内容上出现了不一致,此时如果CPU去读取device传到RAM的DMA缓冲区中的数据,它将直接从cache获得数据,这些数据显然不是它所期望的,因为cache对应的RAM中的数据已经更新了。
解决问题
就cache一致性问题,不同的体系架构有不同的策略,有些是在硬件层面予以保证(x86平台)有些没有硬件支持而需要软件的参与(ARM品台)。
Linux内核中的通用DMA尽力为设备驱动程序提供统一的接口来处理cache缓存一致性的问题,
而将大量品台相关的代码对设备驱动程序隐藏起来。
DMA 的映射方式
1. 一致性DMA映射
linux内核DMA层为一致性DMA映射提供的接口函数为dma_alloc_coherent()
一致性所获得的DMA缓冲区的大小都是页面的整数倍,如果驱动程序需要更小的DMA一致性的DMA缓冲区,则应该使用内核提供的DMA池(pool)机制
对于一致性DMA映射,在分配DMA缓冲区时各平台相关代码已经从根本上解决了cache一致性问题.
但是,一致性映射也会遇到无法克服的困难,主要是指驱动程序中使用的DMA缓冲区并非由驱动程序分配,
而 大专栏 Java NIO-09-零拷贝之 DMA是来自其他模块(如网络设备驱动程序中用于数据包传输的skb->data所指向的缓冲区),此时需要流式DMA映射。
2. 流式DMA映射
流式DMA映射的特点是DMA传输通道使用的缓冲区不是由当前驱动程序自身分配的,而且往往对每次DMA传输都会重新建立一个流式映射的缓冲区,所以使用流式DMA映射时,
设备驱动程序必须小心负责处理可能出现的cache一致性。
linux内核DMA层为设备驱动提供的建立流式DMA映射的函数—dma_map_single
3. 分散/聚集DMA映射
分散/聚集DMA映射通过将虚拟地址上分散的DMA缓冲区通过一个struct scatterlist的数组或链表组织起来,然后通过一次的DMA传输操作在主存RAM与设备之间传输数据。
分散/聚集DMA映射本质上是通过一次DMA操作把内存中分散的数据块在主存与设备之间进行传输,对于其中的每个数据块内核都会建立对应的一个流式DMA映射。
需要设备的支持。
回弹缓冲区
如果CPU侧虚拟地址对应的物理地址不适合设备的DMA操作,那么需要建立回弹缓冲区,相当于一个 中转站,把数据往设备传输时,驱动程序需要把CPU给的数据拷贝到回弹缓冲区,然后再启动DMA操作。
DMA池
由于DMA映射所建立的缓冲区是单个页面的整数倍,如果驱动程序需要更小的一致性映射的DMA缓冲区,可以使用内核提供的DMA池机制(非常类似于Linux内存管理中的slab机制).
个人收获
参考资料
嵌入式Linux——DMA:在内核中简单使用DMA实现内存中数据传递
https://www.xuebuyuan.com/3235513.html
https://www.cnblogs.com/lihuidashen/p/4470678.html
Java NIO-09-零拷贝之 DMA的更多相关文章
- NIO 与 零拷贝
零拷贝介绍 零拷贝是网络编程的关键, 很多性能优化都需要零拷贝. 在 Java程序中, 常用的零拷贝方式有m(memory)map[内存映射] 和 sendFile.它们在OS中又是怎样的设计? NI ...
- 【Java】Java中的零拷贝
物理内存 计算机物理内存条的容量,比如我们买电脑会关注内存大小有多少G,这个容量就是计算机的物理内存. 虚拟内存 操作系统为每个进程分配了独立的虚拟地址空间,也就是虚拟内存,虚拟地址空间又分为用户空间 ...
- Linux、JDK、Netty中的NIO与零拷贝
一.先理解内核空间与用户空间 Linux 按照特权等级,把进程的运行空间分为内核空间和用户空间,分别对应着下图中, CPU 特权等级分为4个,Linux 使用 Ring 0 和 Ring 3. 内核空 ...
- Java IO和Java NIO在文件拷贝上的性能差异分析
1. 在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取到用户空间的缓冲区 ...
- 框架篇:Linux零拷贝机制和FileChannel
前言 大白话解释,零拷贝就是没有把数据从一个存储区域拷贝到另一个存储区域.但是没有数据的复制,怎么可能实现数据的传输呢?其实我们在java NIO.netty.kafka遇到的零拷贝,并不是不复制数据 ...
- 零拷贝详解 Java NIO学习笔记四(零拷贝详解)
转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...
- 零拷贝的原理及Java实现
在谈论Kafka高性能时不得不提到零拷贝.Kafka通过采用零拷贝大大提供了应用性能,减少了内核和用户模式之间的上下文切换次数.那么什么是零拷贝,如何实现零拷贝呢? 什么是零拷贝 WIKI中对其有如下 ...
- NIO零拷贝的深入分析
深入分析通过Socket进行数据文件传递中的传统IO的弊端以及NIO的零拷贝实现原理,及用户空间和内核空间的切换方式 传统的IO流程 在这个过程中: 数据从磁盘拷贝进内核空间缓冲区 从内核空间缓冲区拷 ...
- 转载一篇关于kafka零拷贝(zero-copy)通俗易懂的好文
原文地址 https://www.cnblogs.com/yizhou35/p/12026263.html 零拷贝就是一种避免CPU 将数据从一块存储拷贝到另外一块存储的技术. DMA技术是Direc ...
- kafka零拷贝
Kafka之所以那么快的另外一个原因就是零拷贝(zero-copy)技术.本文我们就来了解Kafka中使用的零拷贝技术为什么那么快. 传统的文件拷贝 传统的文件拷贝通常需要从用户态去转到核心态,经过r ...
随机推荐
- 五、Shell脚本高级编程实战第五部
一.条件表达式 在bash的各种流程控制结构中通常要进行各种测试,然后根据测试结果执行不同的操作.有时也和if结合,让我们方便判断. test: 1)判断文件是否存在:test -f file 2) ...
- Linux实验总结(第二周)
测试一--vi 每个.c一个文件,每个.h一个文件,文件名中最好有自己的学号 用Vi输入图中代码,并用gcc编译通过 在Vi中使用K查找printf的帮助文档 提交vi编辑过程截图,要全屏,包含自己的 ...
- linux epoll ET边沿触发
/***EPOLL ET 触发必须使用非阻塞,LT触发可以阻塞/非阻塞.*read 函数 非阻塞读需 忙轮寻 soket关闭返回0,循环读完数据*如果已经读完再读read返回 -1,errno=11( ...
- Hbase的极限测试经验之java项目的jar包导入
Hbase的极限测试的内容是把之前编过的网站的后台数据库改成hbase即可. 我很快就在hbase数据库中建完表,也把关于操作数据库的函数写好了. 当我调试时,发现在jsp中的操作数据库的函数都不能用 ...
- 894A. QAQ#(暴力)
题目出处:http://codeforces.com/problemset/problem/894/A 题目大意:计数依次出现QAQ的次数 #include<iostream> using ...
- 28)PHP,数据库连接类
PHP代码展示: <?php //类名,也习惯上(推荐)使用跟文件名相似的名字 //定义一个类,该类可以连接mysql数据库 //并连接后返回资源(或失败就终止) class mysqlDB{ ...
- 54)PHP,访问修饰符
类外就是你再实例化成对象的时候 用你类里面的变量 继承的类内, 就是子类里面,但是实例化对象时,不能用 本类内, 只在本类的定义时用,子类不能用.
- 吴裕雄--天生自然python Google深度学习框架:MNIST数字识别问题
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data INPUT_NODE = 784 ...
- centos7 部署vue项目(前后端分离、nginx)
一.环境准备 1.centos7系统 2.mysql数据库 3.在centos7虚拟机上安装好nginx 二.部署内容准备 1.后端war包 或者可执行jar 因为我这里是spring boot项目. ...
- KVC解析
• 阅读 valueForKey (总体规划,先找相关方法,再找相关变量) 1.先是找相关方法,如果方法找不到 2.那么去判断 1 2 3 + (BOOL)accessInstanceVariab ...