news 2026/5/25 15:45:41

内存申请和使用的场景分析(以AP->kernal->ISP为例)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
内存申请和使用的场景分析(以AP->kernal->ISP为例)

在 ISP(Image Signal Processor)系统中,AP 与 ISP 之间的内存交互本质上是一个**“AP 申请可 DMA 访问的共享内存 → 内核建立映射 → 硬件寻址读写 → 同步与回收”**的过程。下面按数据流分层详细拆解。


一、ISP 内存需求的特殊性

与普通应用内存不同,ISP 使用的内存有严格约束:

特性要求原因
物理连续性最好物理连续(或 IOMMU 映射)ISP DMA 通常按物理地址突发传输
Cache 一致性必须显式同步AP(带 Cache)与 ISP(无 Cache)同读写
大页/对齐通常 4KB/64KB/1MB 对齐DMA 效率、页表映射要求
安全/隔离可能需要 TrustZone 隔离保护 RAW 图像等敏感数据

二、整体架构与角色

┌─────────────────────────────────────────┐ │ 用户空间 (Camera HAL / APP) │ │ 调用 ioctl/mmap │ ├─────────────────────────────────────────┤ │ 内核空间 (V4L2 / ISP Driver) │ │ ┌─────────┐ ┌─────────┐ ┌────────┐ │ │ │ CMA/ION │ │DMA-BUF │ │IOMMU │ │ │ │ 分配器 │ │ 框架 │ │/SMMU │ │ │ └────┬────┘ └────┬────┘ └───┬────┘ │ ├────────┼────────────┼───────────┼──────┤ │ APB/AHB/AXI 总线 │ │ │ ├────────┼────────────┼───────────┼──────┤ │ ▼ ▼ ▼ │ │ ┌─────────────────────────────────┐ │ │ │ ISP 硬件 │ │ │ │ (DMA 控制器 → 处理流水线) │ │ │ └─────────────────────────────────┘ │ └─────────────────────────────────────────┘

三、内存申请与下发的完整流程

阶段 1:用户态发起 Buffer 请求

Camera HAL(如 Android CamX/HAL3)通过V4L2(Video4Linux2)或厂商私有接口请求图像 Buffer:

// 典型调用链ioctl(fd,VIDIOC_REQBUFS,&req);// 申请 N 个 Bufferioctl(fd,VIDIOC_QUERYBUF,&buf);// 查询 Buffer 信息mmap(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,offset);// 映射到用户态

关键参数req.memory = V4L2_MEMORY_DMABUFV4L2_MEMORY_MMAP


阶段 2:内核态分配内存(多种机制)

ISP 驱动在内核态根据平台选择不同的分配器:

方式 A:CMA(Contiguous Memory Allocator)—— 最常用
// ISP 驱动中structpage*page=dma_alloc_from_contiguous(dev,count,order);phys_addr_tphys=page_to_phys(page);// 物理地址(ISP DMA 直接用这个)
  • 内核启动时预留一片物理连续内存cma=64M等参数)。
  • 适合 ISP 输入/输出需要大段物理连续地址的场景。
方式 B:ION / DMA-BUF —— 现代主流(Android/Linux)
// 分配共享 Bufferintfd=ion_alloc(len,heap_id_mask,flags);// 旧 ION// 或structdma_buf*dmabuf=dma_buf_export(...);// 标准 DMA-BUF
  • ION(Android)或DMA-BUF(Linux 主线)分配文件描述符化的内存
  • 支持物理不连续内存(通过IOMMU/SMMU映射为 ISP 可见的 IOVA)。
  • 零拷贝共享:AP、ISP、GPU、VPU 都可以通过 fd 共享同一块内存。
方式 C:SMMU/IOMMU 映射(离散内存聚合)

如果系统没有足够大的连续物理内存:

物理页: [Page0 @ 0x1000] [Page1 @ 0x5000] [Page2 @ 0x3000] // 物理不连续 ↓ SMMU 页表映射 IOVA: [0x80000000] [0x80001000] [0x80002000] // ISP 看到的"连续"地址
// 驱动代码示例iova=iommu_map(domain,iova,phys,size,IOMMU_READ|IOMMU_WRITE);// 将 IOVA 写入 ISP 寄存器,ISP 以为自己访问的是连续地址

阶段 3:地址下发给 ISP 硬件

这是核心步骤。驱动将内存地址配置到 ISP 的寄存器中:

// ISP 驱动:配置 DMA 读写地址voidisp_config_buffer(structisp_device*isp,structisp_buffer*buf){phys_addr_tdma_addr=buf->dma_addr;// 物理地址或 IOVA// 写入 ISP 寄存器(通过 AXI/APB 总线)writel(dma_addr,isp->base+ISP_REG_DMA_SRC_ADDR);// 输入 RAW 地址writel(dma_addr+offset_y,isp->base+ISP_REG_DMA_DST_ADDR_Y);// 输出 Y 地址writel(dma_addr+offset_uv,isp->base+ISP_REG_DMA_DST_ADDR_UV);// 输出 UV 地址// 配置长度、stride、格式等writel(buf->size,isp->base+ISP_REG_DMA_SIZE);}

关键概念

  • ISP 是总线主设备(Bus Master),内置 DMA 控制器。
  • 它直接通过AXI/AHB总线发起读写,不需要 CPU 干预。
  • CPU 只需告诉 ISP"数据在物理地址0x8A000000处,去取吧"。

阶段 4:Cache 同步(数据一致性)

AP(CPU)写数据到内存后,如果 ISP 直接读取,可能读到 Cache 里的旧数据(因为内存里的数据还没回写)。必须在下发前做Cache 同步

// 方式 1:写回并无效化 Cache(最常用)dma_sync_sg_for_device(dev,sglist,nents,DMA_TO_DEVICE);// CPU → 内存 → ISPdma_sync_sg_for_cpu(dev,sglist,nents,DMA_FROM_DEVICE);// ISP → 内存 → CPU// 方式 2:分配时标记为 Non-Cacheable(简单但性能差)dma_alloc_attrs(dev,size,&dma_handle,GFP_KERNEL,DMA_ATTR_NON_CONSISTENT);// 方式 3:硬件自动一致性(ARM CCI/DSU 等,高端平台支持)

典型时序

  1. AP 填充图像数据到 Buffer(走 Cache)。
  2. dma_sync_sg_for_device():把 Cache 脏数据刷回内存。
  3. 下发地址给 ISP,启动 ISP。
  4. ISP DMA 读内存 → 处理 → 写回内存。
  5. ISP 中断通知 AP 完成。
  6. dma_sync_sg_for_cpu():无效化 CPU Cache,确保 AP 读到最新数据。

阶段 5:中断回收与 Buffer 轮转

ISP 处理完后通过中断通知 AP:

ISP 完成帧处理 ──→ 触发 IRQ ──→ ISP 驱动 ISR ──→ V4L2 唤醒用户态 │ ▼ 将 Buffer 标记为 DONE 用户态 dequeue 取走图像 空 Buffer 重新 enqueue 给 ISP

这是典型的"生产者-消费者"环形队列(Ring Buffer)模型:

  • AP 预先分配 N 个 Buffer(如 4~8 个)组成队列。
  • ISP 处理完一个,AP 填下一个,实现流水线并行。

四、一个完整的代码级流程示例

以 Linux V4L2 + CMA + 物理连续内存为例:

// ========== 1. 驱动初始化:预留/申请 CMA ==========staticintisp_probe(structplatform_device*pdev){structisp_dev*isp=devm_kzalloc(&pdev->dev,sizeof(*isp),GFP_KERNEL);// 从 CMA 分配 3 个 Buffer(用于 Triple Buffering)for(i=0;i<3;i++){isp->buf[i].vaddr=dma_alloc_coherent(&pdev->dev,SIZE,&isp->buf[i].dma_addr,GFP_KERNEL);// dma_addr: ISP 用的物理地址// vaddr: CPU 用的虚拟地址}}// ========== 2. 用户态请求 Buffer ==========staticintisp_reqbufs(structfile*file,void*priv,structv4l2_requestbuffers*p){// 将内核分配的 dma_addr 通过 mmap 暴露给用户态// 用户态拿到虚拟地址,可直接读写}// ========== 3. 下发配置并启动 ISP ==========staticvoidisp_start_streaming(structisp_dev*isp){structisp_buffer*buf=list_first_entry(&isp->ready_list,...);// Cache 同步:CPU 写的数据刷到内存dma_sync_single_for_device(isp->dev,buf->dma_addr,buf->size,DMA_TO_DEVICE);// 配置 ISP 硬件寄存器writel(buf->dma_addr,isp->base+ISP_DMA_ADDR_REG);writel(0x1,isp->base+ISP_START_REG);// GO! ISP 开始 DMA}// ========== 4. 中断处理 ==========staticirqreturn_tisp_irq_handler(intirq,void*dev_id){structisp_dev*isp=dev_id;// 同步 Cache:让 CPU 能看到 ISP 写的新数据dma_sync_single_for_cpu(isp->dev,buf->dma_addr,buf->size,DMA_FROM_DEVICE);// 唤醒等待的进程vb2_buffer_done(&buf->vb,VB2_BUF_STATE_DONE);// 切换下一个 Bufferisp_switch_buffer(isp);returnIRQ_HANDLED;}

五、关键问题与优化

问题解决方案
物理内存不够连续使用 IOMMU/SMMU 做 IOVA 映射,或增大 CMA 预留
Cache 不同步花屏严格使用dma_sync_*接口,或分配 Non-Cacheable 内存
Buffer 切换延迟Triple/Quad Buffering,ISP 处理时 AP 准备下一帧
安全域隔离TrustZone + Secure Memory,ISP 安全通路访问安全内存
跨 IP 共享使用 DMA-BUF fd,ISP、GPU、VPU 零拷贝共享

六、总结

AP 向 ISP 下发内存的完整链路可以概括为:

  1. 申请:AP(用户态)通过 V4L2 → 内核驱动调用dma_alloc_coherent/ion_alloc/dma_buf分配物理连续或 IOMMU 映射的内存。
  2. 映射:内核返回物理地址(或 IOVA)给驱动,同时通过mmap映射虚拟地址到用户态。
  3. 同步:AP 填完数据后,调用dma_sync_*_for_device刷 Cache。
  4. 下发:驱动将物理地址/IOVA 写入 ISP 的 DMA 寄存器。
  5. 硬件读写:ISP 通过 AXI 总线直接 DMA 读写内存,无需 CPU 参与。
  6. 中断回传:ISP 完成触发中断,驱动同步 Cache 并通知 AP 取数据。

理解这个流程的关键在于:ISP 是独立的总线主设备,CPU 只负责"指路和同步",实际搬运由 DMA 完成。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/25 15:45:36

跨平台有害内容检测:从数据构建到模型泛化的实战指南

1. 项目概述&#xff1a;在线有害内容检测的现状与挑战在今天的数字世界里&#xff0c;我们每天都会在社交媒体、新闻评论区或论坛上看到海量的用户生成内容。作为一名长期关注内容安全与自然语言处理&#xff08;NLP&#xff09;应用的研究者和实践者&#xff0c;我深刻体会到…

作者头像 李华
网站建设 2026/5/25 15:42:22

终极歌词下载工具ZonyLrcToolsX:一键批量获取四大平台高质量歌词

终极歌词下载工具ZonyLrcToolsX&#xff1a;一键批量获取四大平台高质量歌词 【免费下载链接】ZonyLrcToolsX ZonyLrcToolsX 是一个能够方便地下载歌词的小软件。 项目地址: https://gitcode.com/gh_mirrors/zo/ZonyLrcToolsX 还在为本地音乐库缺少歌词而烦恼吗&#xf…

作者头像 李华
网站建设 2026/5/25 15:40:08

机器学习势函数在碳化硅极端环境模拟中的应用与验证

1. 项目概述&#xff1a;当机器学习“学会”了原子间的“对话”在材料科学的前沿&#xff0c;尤其是在核能、航空航天和极端环境电子器件领域&#xff0c;碳化硅&#xff08;SiC&#xff09;正扮演着越来越关键的角色。这种材料以其卓越的硬度、高热导率、高击穿电压和优异的抗…

作者头像 李华
网站建设 2026/5/25 15:36:01

Frida安卓逆向实战:从零部署到Java/Native层Hook

1. 这不是“装个 Frida 就能 hook”的速成课&#xff0c;而是你真正搞懂安卓逆向起点的实操切口很多人第一次听说 Frida&#xff0c;是在某篇“三行代码绕过登录验证”的短视频标题里。点进去一看&#xff0c;黑框里敲几行 js&#xff0c;App 真就跳过了账号密码直接进首页——…

作者头像 李华
网站建设 2026/5/25 15:33:06

免费解锁WeMod专业版功能:2026终极完整指南与安全使用教程

免费解锁WeMod专业版功能&#xff1a;2026终极完整指南与安全使用教程 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer 还在为WeMod专业版的高昂订阅费用…

作者头像 李华