linux 之dma_buf (8)- ION简化版本
一、前言
我们学习了如何使用 alloc_page() 方式来分配内存,但是该驱动只能分配1个PAGE_SIZE。本篇我们将在上一篇的基础上,实现一个简化版的ION驱动,以此来实现任意 size 大小的内存分配。
二、准备
为了和 kernel 标准 ion 驱动兼容,本篇引用了 driver/staging/android/uapi/ion.h
头文件,目的是为了方便 userspace 直接使用 struct ion_allocation_data
和 ION_IOC_ALLOC
宏:
struct ion_allocation_data {__u64 len;__u32 heap_id_mask;__u32 flags;__u32 fd;__u32 unused; };#define ION_IOC_MAGIC 'I' #define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \struct ion_allocation_data)
本篇 ion 驱动只使用 ion_allocation_data 结构体中的 len 和 fd 这两个元素,其它元素不做处理。
三、示例
exporter-ion.c
#include <linux/dma-buf.h>
#include <linux/highmem.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>struct ion_allocation_data {__u64 len;__u32 heap_id_mask;__u32 flags;__u32 fd;__u32 unused;
};#define ION_IOC_MAGIC 'I'
#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \struct ion_allocation_data)struct ion_data {int npages;struct page *pages[];
};static int ion_attach(struct dma_buf *dmabuf, struct device *dev,struct dma_buf_attachment *attachment)
{pr_info("dmabuf attach device: %s\n", dev_name(dev));return 0;
}static void ion_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attachment)
{pr_info("dmabuf detach device: %s\n", dev_name(attachment->dev));
}static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment,enum dma_data_direction dir)
{struct ion_data *data = attachment->dmabuf->priv;struct sg_table *table;struct scatterlist *sg;int i;table = kmalloc(sizeof(*table), GFP_KERNEL);sg_alloc_table(table, data->npages, GFP_KERNEL);sg = table->sgl;for (i = 0; i < data->npages; i++) {sg_set_page(sg, data->pages[i], PAGE_SIZE, 0);sg = sg_next(sg);}dma_map_sg(NULL, table->sgl, table->nents, dir);return table;
}static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment,struct sg_table *table,enum dma_data_direction dir)
{dma_unmap_sg(NULL, table->sgl, table->nents, dir);sg_free_table(table);kfree(table);
}static void ion_release(struct dma_buf *dma_buf)
{struct ion_data *data = dma_buf->priv;int i;pr_info("dmabuf release\n");for (i = 0; i < data->npages; i++)put_page(data->pages[i]);kfree(data);
}
static void *ion_vmap(struct dma_buf *dma_buf)
{struct ion_data *data = dma_buf->priv;return vm_map_ram(data->pages, data->npages, 0, PAGE_KERNEL);
}static void ion_vunmap(struct dma_buf *dma_buf, void *vaddr)
{struct ion_data *data = dma_buf->priv;vm_unmap_ram(vaddr, data->npages);
}static int ion_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
{struct ion_data *data = dma_buf->priv;unsigned long vm_start = vma->vm_start;int i;for (i = 0; i < data->npages; i++) {remap_pfn_range(vma, vm_start, page_to_pfn(data->pages[i]),PAGE_SIZE, vma->vm_page_prot);vm_start += PAGE_SIZE;}return 0;
}static int ion_begin_cpu_access(struct dma_buf *dmabuf,enum dma_data_direction dir)
{struct dma_buf_attachment *attachment;struct sg_table *table;attachment = list_first_entry(&dmabuf->attachments, struct dma_buf_attachment, node);table = attachment->sgt;dma_sync_sg_for_cpu(NULL, table->sgl, table->nents, dir);return 0;
}static int ion_end_cpu_access(struct dma_buf *dmabuf,enum dma_data_direction dir)
{struct dma_buf_attachment *attachment;struct sg_table *table;attachment = list_first_entry(&dmabuf->attachments, struct dma_buf_attachment, node);table = attachment->sgt;dma_sync_sg_for_device(NULL, table->sgl, table->nents, dir);return 0;
}static const struct dma_buf_ops exp_dmabuf_ops = {.attach = ion_attach,.detach = ion_detach,.map_dma_buf = ion_map_dma_buf,.unmap_dma_buf = ion_unmap_dma_buf,.release = ion_release,.mmap = ion_mmap,.vmap = ion_vmap,.vunmap = ion_vunmap,.begin_cpu_access = ion_begin_cpu_access,.end_cpu_access = ion_end_cpu_access,
};
static struct dma_buf *ion_alloc(size_t size)
{DEFINE_DMA_BUF_EXPORT_INFO(exp_info);struct dma_buf *dmabuf;struct ion_data *data;int i, npages;npages = PAGE_ALIGN(size) / PAGE_SIZE;data = kmalloc(sizeof(*data) + npages * sizeof(struct page *),GFP_KERNEL);data->npages = npages;for (i = 0; i < npages; i++)data->pages[i] = alloc_page(GFP_KERNEL);exp_info.ops = &exp_dmabuf_ops;exp_info.size = npages * PAGE_SIZE;exp_info.flags = O_CLOEXEC;exp_info.priv = data;dmabuf = dma_buf_export(&exp_info);return dmabuf;
}static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{struct dma_buf *dmabuf;struct ion_allocation_data alloc_data;/* currently just only support ION_IOC_ALLOC ioctl */if (cmd != ION_IOC_ALLOC)return -EINVAL;copy_from_user(&alloc_data, (void __user *)arg, sizeof(alloc_data));dmabuf = ion_alloc(alloc_data.len);alloc_data.fd = dma_buf_fd(dmabuf, O_CLOEXEC);copy_to_user((void __user *)arg, &alloc_data, sizeof(alloc_data));return 0;
}static struct file_operations ion_fops = {.owner = THIS_MODULE,.unlocked_ioctl = ion_ioctl,
};static struct miscdevice mdev = {.minor = MISC_DYNAMIC_MINOR,.name = "ion",.fops = &ion_fops,
};static int __init ion_init(void)
{return misc_register(&mdev);
}static void __exit ion_exit(void)
{misc_deregister(&mdev);
}module_init(ion_init);
module_exit(ion_exit);
从上面可以看出,任意大小的参数,在驱动中就是for循环申请页。因为申请的内存不一定时连续物理内存,所以使用sg table .
应用程序
ion_test.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>struct ion_allocation_data {__u64 len;__u32 heap_id_mask;__u32 flags;__u32 fd;__u32 unused;
};#define PAGE_SIZE 4096int main(int argc, char *argv[])
{int fd;struct ion_allocation_data alloc_data;fd = open("/dev/ion", O_RDWR);alloc_data.len = 3 * PAGE_SIZE;ioctl(fd, ION_IOC_ALLOC, &alloc_data);printf("ion alloc success: size = %llu, dmabuf_fd = %u\n",alloc_data.len, alloc_data.fd);close(fd);return 0;
}
该应用程序通过 ION_IOC_ALLOC ioctl 请求分配了3个 page 的物理 buffer,如果底层驱动分配成功,则会将该 dma-buf 所对应的 fd 返回给应用程序,以便后续执行 mmap 操作或将 fd 传给其它模块。
需要注意的是,这里的3个 pages 是通过3次调用 alloc_page() 来分配的,因此每个 page 之间可能是不连续的,也可以近似的认为该 ion 驱动分配的 buffer 属于 ION_HEAP_TYPE_SYSTEM。如果要分配物理连续的 pages,请使用 alloc_pages() 进行分配。
上面的驱动中,通过变长数组,实现虚拟地址连续,但是物理地址不一定连续的方法。
相关文章:
linux 之dma_buf (8)- ION简化版本
一、前言 我们学习了如何使用 alloc_page() 方式来分配内存,但是该驱动只能分配1个PAGE_SIZE。本篇我们将在上一篇的基础上,实现一个简化版的ION驱动,以此来实现任意 size 大小的内存分配。 二、准备 为了和 kernel 标准 ion 驱动兼容&…...

⌈ 传知代码 ⌋ 高速公路车辆速度检测软件
💛前情提要💛 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间,对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…...

scrapy 整合 mitm
1.mitm 是什么 MITMproxy 是一个开源的中间人代理,常用于网络流量的拦截、查看和修改。 2.scrapy 整合 mitm步骤 2.1 安装mitm PS F:\studyScrapy\itcastScrapy> pip install mitmproxy2.2 在settings 中配置下载器中间件 # settings.pyDOWNLOADER_MIDDLEWARES…...
linux大文件切割
在一些小众的场景下出现的大文件无法一次性传输 当然我遇到了 ,work中6G镜像文件无法一次性刻盘到4.7G大小的盘 split split -b 3G 源大文件 目标文件 #安静等待会生成目标文件名a、b、c......-b <大小>:指定每个输出文件的大小,单位为…...

图像分割模型LViT-- (Language meets Vision Transformer)
参考:LViT:语言与视觉Transformer在医学图像分割-CSDN博客 背景 标注成本过高而无法获得足够高质量标记数据医学文本注释被纳入以弥补图像数据的质量缺陷半监督学习:引导生成质量提高的伪标签医学图像中不同区域之间的边界往往是模糊的&…...

CANDela studio之CDDT与CDD
CDDT有更高的权限,作为模板规范CDD文件。 CDD可修改的内容比CDDT少。 CDDT根据诊断协议提供诊断格式,主要就是分类服务和定义服务,一般是OEM释放,然后由供应商细化成自己零部件的CDD文件。 在这里举个例子,OEM在CDDT…...
Java中的注解(Annotation)是什么?它们有什么用途?
技术难点 在Java中,注解(Annotation)是一种元数据(metadata)的形式,用于为Java代码(类、方法、变量、参数和包等)提供额外的信息。这些信息在运行时可以通过反射机制进行读取和处理…...

【CUDA】Nsight profile驱动的CUDA优化
前置准备 安装NVIDIA Nsight Compute。 安装好后选择使用管理员权限启动下载官方 Demo 代码官方博客Shuffle warp 1. 任务介绍及CPU版本 1.1 任务介绍 任务理解: 有一个 L x M 的矩阵 M 1 M_1 M1 对其每行取平均值 得到 V 1 ∈ R L 1 V_1 \in \mathbb{R}^{…...
字符串的拼接
字符串拼接方式1 之前的算术运算符,只是用来数值类型进行数学运算的,而string不存在算术运算符不能计算,但是可以通过号来进行字符串拼接。 string str "123"; //用进行拼接 str str "456"; Console.WriteLine(str)…...

HIVE3.1.3+ZK+Kerberos+Ranger2.4.0高可用集群部署
目录 一、集群规划 二、介质下载 三、基础环境准备 1、解压文件 2、配置环境变量 四、配置zookeeper 1、创建主体 2、修改zoo.cfg 3、新增jaas.conf 4、新增java.env 5、重启ZK 6、验证ZK 五、配置元数据库 六、安装HIVE 1、创建Hiver的kerberso主体 2…...

Android ANR Trace日志阅读分析技巧
什么是Trace日志 Trace日志是指ANR目录下的一份txt文件 adb pull /data/anr/traces.txt Trace日志有什么用 分析应用ANR无响应的问题, Trace怎么用 Cmd line: com.xx ABI: arm Build type: optimized Zygote loaded classes3682 post zygote classes3750 Intern…...
前端Ajax、Axios和Fetch的用法和区别笔记
前端 JavaScript 开发中,进行 HTTP 请求的三种主要方式是 Ajax、Axios 和 Fetch。这三种方式各有优缺点,并且适用于不同的场景。在合适的业务场景下使用,以下是它们的区别和使用举例。 1. Ajax Ajax(Asynchronous JavaScript an…...
Android的Framework(TODO)
(TODO)...
牛客小白月赛94 EF题解
题目描述 注:此版本为本题的hard(困难版),与easy(简单版)唯一的不同之处只有数据范围。 小苯有一个容量为 k 的背包,现在有 n 个物品,每个物品有一个体积 v 和价值 w࿰…...
大数据开发面试题【Flink篇】
148、flink架构 flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算 特点: 高吞吐和低延迟:每秒数百万个事件,毫秒级延迟 结果的准确性:提供了事件时间和处理时间语义,提供结果的一致…...
Java技术深度解析:高级面试问题与精粹答案(二)
Java 面试问题及答案 1. 什么是Java的垃圾回收机制?它是如何工作的? 答案: Java的垃圾回收机制(Garbage Collection,GC)是Java运行时环境(JRE)中的一个功能,用于自动管…...
算数运算符
算术运算符是用于数值类型变量计算的运算符。 它的返回结果是数值。 赋值符号 关键知识点:先看右侧,再看左侧,把右侧的值赋值给左侧的变量。 附上代码: string myName "唐唐"; int myAge 18; float myHeight 177.5…...

闲话 .NET(3):.NET Framework 的缺点
前言 2016 年,微软正式推出 .NET Core 1.0,并在 2019 年全面停止 .NET Framework 的更新。 .NET Core 并不是 .NET Framework 的升级版,而是一个从头开始开发的全新平台,一个跟 .NET Framework 截然不同的开源技术框架。 微软为…...
WPF实现简单的3D图形
简述 Windows 演示基础 (WPF) 提供了一种功能,用于根据应用程序要求绘制、转换 3D 图形并为其添加动画效果。它不支持完整的3D游戏开发,但在某种程度上,您可以创建3D图形。 通过组合 2D 和 3D 图形,您还可以…...

设计模式之创建型模式---原型模式(ProtoType)
文章目录 概述类图原型模式优缺点优点缺点 代码实现 概述 在有些系统中,往往会存在大量相同或者是相似的对象,比如一个围棋或者象棋程序中的旗子,这些旗子外形都差不多,只是演示或者是上面刻的内容不一样,若此时使用传…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
API网关Kong的鉴权与限流:高并发场景下的核心实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中,API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关,Kong凭借其插件化架构…...

Qwen系列之Qwen3解读:最强开源模型的细节拆解
文章目录 1.1分钟快览2.模型架构2.1.Dense模型2.2.MoE模型 3.预训练阶段3.1.数据3.2.训练3.3.评估 4.后训练阶段S1: 长链思维冷启动S2: 推理强化学习S3: 思考模式融合S4: 通用强化学习 5.全家桶中的小模型训练评估评估数据集评估细节评估效果弱智评估和民间Arena 分析展望 如果…...
【学习记录】使用 Kali Linux 与 Hashcat 进行 WiFi 安全分析:合法的安全测试指南
文章目录 📌 前言🧰 一、前期准备✅ 安装 Kali Linux✅ 获取支持监听模式的无线网卡 🛠 二、使用 Kali Linux 进行 WiFi 安全测试步骤 1:插入无线网卡并确认识别步骤 2:开启监听模式步骤 3:扫描附近的 WiFi…...

python学习day39
图像数据与显存 知识点回顾 1.图像数据的格式:灰度和彩色数据 2.模型的定义 3.显存占用的4种地方 a.模型参数梯度参数 b.优化器参数 c.数据批量所占显存 d.神经元输出中间状态 4.batchisize和训练的关系 import torch import torchvision import torch.nn as nn imp…...