惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
G
Google Developers Blog
D
Docker
阮一峰的网络日志
阮一峰的网络日志
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
Hugging Face - Blog
Hugging Face - Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
腾讯CDC
T
The Blog of Author Tim Ferriss
Microsoft Security Blog
Microsoft Security Blog
WordPress大学
WordPress大学
I
InfoQ
Engineering at Meta
Engineering at Meta
Stack Overflow Blog
Stack Overflow Blog
Google DeepMind News
Google DeepMind News

Bing's Blog

终不似,少年游 我现在难以输出一篇完整的文章 git-cm:在终端里用 LLM 生成 commit message Token Tracker - 追踪 Coding Agent 的 Token 使用情况 AI Coding 工具的实践经验 2025年终总结 行车记录仪视频拼接 生成文章摘要 Base64压缩 2024年终总结 二维数据可视化工具-painter 对ToB和ToC的感受 C++闭包二 轻量级参数解析库-tiny_cmdline C++标签派发技术
DMA拼接
bing · 2025-04-20 · via Bing's Blog

涉及到DMA应用的场景中,往往一方(比如FPGA)以固定Packet大小向DMA写入数据,另一方(比如CPU)也以固定Packet大小读出(或直接在DMA上操作)数据。一般情况下,为了提高DMA利用率,CPU处理的数据结构不一定正好是Packet大小的因子(packed模式),在这种场景下会涉及到数据的拼接问题。

我们以直接在DMA上操作数据为例。

一般情况

在上图中,Packet是可以和DMA大小对齐的,但是被处理的数据结构却不是。这时候,最后一个数据结构DN就需要拼接:

  1. 计算数据结构的大小-data_size
  2. 计算packet 63中DN占用的大小-dn_leftover_size
  3. 拷贝dn_leftover_size到临时buffer
  4. packet 0来到,从packet 0拷贝data_size - dn_leftover_size和临时buffer拼接组成一个完整的数据结构

作为对比,对D1的操作是:

  1. 计算数据结构的大小-data_size
  2. 计算packet 0中D1占用的大小-d1_leftover_size
  3. Packet 1来到,指针向左偏移d1_leftover_size, 组成一个完整的数据结构

对比DN数据,D1可以避免内存拷贝。

对DN是否也可以呢?很自然的想法是,如果DMA是一个真正的环,那么就可以。能否做到呢?

这种设想如下图:

DMA环-用户视角

要知道,CPU为了能够access DMA,需要做一次mmap映射,要解决这个问题,就关系到这种映射是否可以一对多。是可以的。

  1. 首先常规映射, 整块DMA映射到用户空间的某个起始地址,比如address_dma
  2. DMA最后一个packet,再映射到address_dma - packet_size

那么从CPU看来,packet 0向前推,就变成了 packet 63,连起来了!

从实现逻辑看,操作是:

  1. 计算DMA的大小-dma_size
  2. 计算一个Packet的大小-packet_size
  3. mmap一个MAP_ANONYMOUS | MAP_PRIVATE的内存,大小为dma_size + packet_size, 得到virtual_total_address
  4. 把packet 63以MAP_SHARED | MAP_FIXED方式mmap到virtual_total_address, 大小是packet_size
  5. 把DMA的起始地址以MAP_SHARED | MAP_FIXED方式mmap到virtual_total_address + packet_size, 大小是dma_size

这样,映射就完成了,从用户空间来看,packet 63和packet 0也是连起来的。

类似的,对于文件,我们也可以通过mmap映射的方法,做到虚拟拼接。把多个小文件,虚拟成一个大文件,或者一个大文件虚拟成多个小文件。