Linux DMA-Buf驱动框架
一、DMABUF 框架
dmabuf 是一个驱动间共享buf 的机制,他的简单使用场景如下:
用户从DRM(显示驱动)申请一个dmabuf,把dmabuf 设置给GPU驱动,并启动GPU将数据输出到dmabuf,GPU输出完成后,再将dmabuf设置到DRM 驱动,完成画面的显示。
在这个过程中通过共享dmabuf的方式,避免了GPU输出数据拷贝到drm frame buff的动作。
如下所示,dmabuf 框架分为用户层和驱动层,用户层可以通过 /dev/dmabuf_heap/xxx节点,从名称为xxx的dma heap 中申请dmabuf。申请到的dmabuf 在用户层的视角就是一个文件,并由fd 标识一个dmabuf。将fd 通过DRM、GPU接口传给驱动,驱动就能共享这个dmabuf。
以下是一个简单的dmabuf 的示例代码:
int fd, dmabuf_fd;
struct dma_heap_allocation_data data;
struct pollfd fds;data.len = 1024 * 1024 * 4;
//打开dma heap
fd = open("/dev/dma-heap/xxx");//从dma heap 申请dmabuf
ioctl(fd, DMA_HEAP_IOCTL_ALLOC, &data);//将dmabuf的fd 设置到gpu进行处理
set_dmabuf_to_gpu(data.fd);//等待gpu 输出完毕
fds.fd = data.fd;
fds.events = POLLIN | POLLOUT;
poll(fds, 1, TIMEOUT);//将dmabuf 设置到drm显示
set_dmabuf_to_drm(data.fd);//等待显示完成
poll(fds, 1, TIMEOUT);//释放dmabuf
close(data.fd);
二、DMA Heap
dma heap 就是一个dmabuf 内存池,让用户可以从内存池中申请dmabuf。其代码主要在dma-heap.c,设备驱动可以创建自己的dma heap,从而提供给用户申请dmabuf。例如DRM驱动可以创建一个DRM dma heap。DRM驱动最重要的就算实现struct dma_heap_ops 对象,这个对象需要实现allocate() 函数,即当用户从dma heap 申请dmabuf 时,DRM驱动要如何分配真实的物理内存。
struct dma_heap_ops {int (*allocate)(struct dma_heap *heap,unsigned long len,unsigned long fd_flags,unsigned long heap_flags);
};struct dma_heap {const char *name;const struct dma_heap_ops *ops; //主要实现申请dmabuf的回调函数void *priv;dev_t heap_devt;struct list_head list;struct cdev heap_cdev;
};
dma-heap.c 中其他的代码主要是实现一个简单设备驱动,提供接口给用户。
三、dmabuf
3.1、dmabuf使用场景
在dmabuf 的使用场景中,有两种驱动:exporter 和 importer。
- exporter 是dmabuf 的提供者,是实现dma heap的驱动程序,负责dmabuf 对应的物理内存的申请、释放、映射等实现。
- importer 是dmabuf的使用者,是使用dmabuf 进行输入输出数据的驱动程序,他不关心dmabuf的申请释放,只需要往dmabuf 里读写数据即可。
像上述例子中,DRM驱动首先是exporter,允许用户从dma heap申请内存,又是importer,从dmabuf 中读取数据显示到屏幕。而GPU是纯纯的importer,向dmabuf 中写入数据。
这两种角色的关系如下图所示:
从上述图可见dma_buf_ops 的实现至关重要。所以接下来我们关注dmabuf是如何被创建的。
3.2、dmabuf的创建
dmabuf 是如何从dma heap 中被申请出来的?这部分主要是在allocate回调函数实现的,在大部分驱动中,allocate回调函数中会从物理内存中申请内存,并 调用dma_buf_export() 创建一个dmabuf 对象。
所以我们的重点将分析 dma_buf_export() 函数是如何创建一个dmabuf 对象的。
首先还是看dmabuf 的结构体定义:
struct dma_buf {size_t size;struct file *file; //匿名文件,代表该dmabuf,暴露给用户从而支持跨驱动传输struct list_head attachments; //attachment 链表const struct dma_buf_ops *ops; //重要的回调函数void *vmap_ptr; //dmabuf kernel 地址struct dma_resv *resv; //保留区,用于存放dma fence对象/* poll support */wait_queue_head_t poll; //等待队列,用于pollstruct dma_buf_poll_cb_t {struct dma_fence_cb cb;wait_queue_head_t *poll;__poll_t active;} cb_excl, cb_shared; //用于poll、dma fence
};
以下是dma_buf_export() 的简略版,很简单就是根据exp_info 初始化dmabuf对象,并创建一个文件,将dmabuf 与文件绑定起来。
struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
{//初始dmabuf 对象dmabuf = kzalloc(alloc_size, GFP_KERNEL);dmabuf->priv = exp_info->priv;dmabuf->ops = exp_info->ops;dmabuf->size = exp_info->size;dmabuf->exp_name = exp_info->exp_name;dmabuf->owner = exp_info->owner;spin_lock_init(&dmabuf->name_lock);init_waitqueue_head(&dmabuf->poll);dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll;dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;if (!resv) {resv = (struct dma_resv *)&dmabuf[1];dma_resv_init(resv);}dmabuf->resv = resv;//初始化filefile = dma_buf_getfile(dmabuf, exp_info->flags);file->f_mode |= FMODE_LSEEK;dmabuf->file = file;mutex_init(&dmabuf->lock);INIT_LIST_HEAD(&dmabuf->attachments);//添加到全局链表mutex_lock(&db_list.lock);list_add(&dmabuf->list_node, &db_list.head);mutex_unlock(&db_list.lock);return dmabuf;
}
3.3、dma_buf_ops
exporter驱动只关注struct dma_buf_export_info 对象即可,最重要的是struct dma_buf_ops对象的实现,这点需要根据具体的驱动实现。所以下面分析这些回调函数的含义是什么:
struct dma_buf_ops {//判断当前设备是否能够访问dmabuf的物理内存,一些物理内存只能由指定的设备访问如vram。若设备可以访问改物理内存,则返回一个attachment代表此次访问int (*attach)(struct dma_buf *, struct dma_buf_attachment *);//释放之前获取的attachmentvoid (*detach)(struct dma_buf *, struct dma_buf_attachment *);//importer 调用这个函数,锁定dmabuf的物理内存,使其不能被迁移int (*pin)(struct dma_buf_attachment *attach);//解锁物理内存void (*unpin)(struct dma_buf_attachment *attach);//将dmabuf的物理内存映射到importer的地址空间,表示importer要开始访问物理内存//因为exporter要让所以attach的设备都能访问,所以可能要将物理内存移动到合适的地址,所以函数可能休眠//返回一个sg_table,表示物理地址散列表struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *,enum dma_data_direction);//解除映射并释放sg_tablevoid (*unmap_dma_buf)(struct dma_buf_attachment *,struct sg_table *,enum dma_data_direction);//释放dmabuf,exporter在这个函数释放私有数据void (*release)(struct dma_buf *);//importer在使用cpu读取dmabuf前,调用该接口让exporter 确保数据在内存上且cpu能读取到正确的数据int (*begin_cpu_access)(struct dma_buf *, enum dma_data_direction);//结束cpu 访问int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction);//将dmabuf 物理内存map 到用户地址空间int (*mmap)(struct dma_buf *, struct vm_area_struct *vma);//将dmabuf 物理内存map到内核地址空间void *(*vmap)(struct dma_buf *);void (*vunmap)(struct dma_buf *, void *vaddr);
};
dmabuf框架将一个驱动访问物理内存的动作拆分成这么多个步骤,目的就是为了多个设备能共享一个物理内存,而每个设备的访问能力,访问地址空间都可能不一样,这就需要将访问过程细细拆分,协调好每个设备的访问顺序和关系。
四、dma-fence
dma fence 是用于做同步的。考虑以下场景:
一个dmabuf,先由GPU完成渲染,然后再交给DRM进行显示输出。那么GPU渲染完成后,如何通知DRM进行显示输出呢?也就是GPU和DRM之前如何进行同步?这就需要引入fence用于设备间的同步,fence用于表示一个操作的完成状态,故fence有两个状态,not done和done。
首先GPU在开始渲染操作前,创建一个fence,注册回调函数,将fence添加到dmabuf 中,随后DRM 等待该fence done。当GPU渲染完成中断上来后,会通知fence done。随后DRM线程被唤醒,进行显示操作。
另外,dma fence还需要考虑多设备访问的情况,即可能有多个设备在等待fence完成,那么fence就必须支持多个设备的等待。
那么就先看dma fence的定义:
struct dma_fence {spinlock_t *lock;const struct dma_fence_ops *ops;union {struct list_head cb_list; //回调函数链表,每个等待fence的驱动,都需要注册一个回调节点到该链表,当fence done时,会遍历该链表执行所有驱动的回调函数。/* @cb_list replaced by @timestamp on dma_fence_signal() */ktime_t timestamp;/* @timestamp replaced by @rcu on dma_fence_release() */struct rcu_head rcu;};u64 context;u64 seqno;unsigned long flags;struct kref refcount;int error;
};
如图所示:GPU线程会在操作dmabuf 前,创建fence,并等待fence完成,同时DRM也会等待该fence完成。当GPU渲染完成中断产生后,会调用fence done,依次唤醒GPU、DRM线程,GPU线程此时就可以继续下一帧图像的渲染,而DRM就可以将已经完成渲染的图像显示到屏幕。
这个过程中调用的接口有:
- dma_fence_init():初始化一个dma fence对象
- dma_resv_reserve_shared() :从dma resv 中保留一个share fence 指针
- dma_resv_add_shared_fence():将dma fence添加到resv 对象
- dma_fence_default_wait():向dma fence注册回调函数dma_fence_default_wait_cb,并睡眠等待dma fence完成
- dma_fence_signal():标志dma fence 完成,并回调dma fence 中的所有回调函数
其中有一个叫dma_resv的对象,简单来说dma_resv 是一个存放dma fence的地方,一个dmabuf 可能同时有若干个dma fence,且dma fence还有共享和独占两种。dma_resv可以理解为一块内存区域,专门存放dma fence的,故要将dma fence添加到dmabuf时,要先调用dma_resv_reserve_shared() 预留出dma fence的位置,然后再调用dma_resv_add_shared_fence() 添加到dma resv。
五、poll
前面所述都是在内核态,但对于用户来说,也希望获取到设备的同步信息。例如在本文一开始的例子中,用户会使用poll 系统调用等待gpu渲染完成。这一切都是由dma_buf_fops来实现的。
在3.2中提到dmabuf的创建中,有一个步骤会创建匿名文件,这个匿名文件就是用于暴露给用户的接口。这个文件代表了一个dmabuf,用户通过该文件的fd可以操作该dmabuf的一些功能,dma_buf_fops是所有dmabuf 共享的file_operations,其中就包括poll的实现。
当用户调用poll 系统调用等待dmabuf时,会遍历dmabuf 上的所有fence,并将回调函数dma_buf_poll_cb注册到每一个fence上,并进入休眠。当有任意一个fence done时,就会唤醒用户线程,从而退出poll。
相关文章:
Linux DMA-Buf驱动框架
一、DMABUF 框架 dmabuf 是一个驱动间共享buf 的机制,他的简单使用场景如下: 用户从DRM(显示驱动)申请一个dmabuf,把dmabuf 设置给GPU驱动,并启动GPU将数据输出到dmabuf,GPU输出完成后…...
MySQL之优化服务器设置(三)
优化服务器设置 InnoDB表空间 InnoDB把数据保存在表空间内,本质上是一个由一个或多个磁盘文件组成的虚拟文件系统。InnoDB用表空间实现很多功能,并不只是存储表和索引。它还保存了回滚日志(旧版本行)、插入缓冲(Insert Buffer)、双写缓冲(Doublewrite …...
如何实现 Python 源码压缩加密常用解决方案详细教程(更新中)
Python是一种高级的、解释型的、面向对象的编程语言,Python 码简洁易读,并且Python语言跨平台,拥有丰富的标准库和第三方库,深受开发人员的喜爱。 Python 程序扩展名 .py:这是 Python 程序的标准文件扩展名。当你创建…...
SAP Build 2-PDF数据提取与决策
0. 安装desktop agent 在后续过程中发现要预先安装desktop agent,否则没法运行自动化流程… 0.1 agent下载 参考官方文档说明 https://help.sap.com/docs/build-process-automation/sap-build-process-automation/create-user-in-rbsc-download-repository?loca…...
【回溯】Leetcode 77. 组合【中等】
组合 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1: 输入: n 4, k 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ] 解题思路 定义递归函数࿱…...
项目中常量的定义方式
方式一 在常量个数少的时候,通常情况下使用这种方式。 public class MqConstants {public static final String EXCHANGE_1 "exchange1";public static final String EXCHANGE_2 "exchange2";public static final String EXCHANGE_3 "…...
BL104钡铼多协议采集网关助力企业智能化转型
BL104钡铼多协议采集网关(PLC物联网关BL104)是为满足工业环境需求而设计的专业工业级协议转换网关。它在企业智能化转型过程中扮演着关键角色,为企业提供了高效、稳定的通信解决方案,助力企业实现智能化转型。 首先,P…...
【LC刷题】DAY08:151 55 28 459
【LC刷题】DAY08:151 55 28 459 文章目录 【LC刷题】DAY08:151 55 28 459151. 反转字符串中的单词 [link](https://leetcode.cn/problems/reverse-words-in-a-string/description/)55. 右旋字符串 [link](https://kamacoder.com/problempage.php?pid106…...
Debian 12.5 一键安装 Oracle 19C 单机
前言 Oracle 一键安装脚本,演示华为 Debian 12.5 一键安装 Oracle 19C 单机版过程(全程无需人工干预)。 ⭐️ 脚本下载地址:Shell脚本安装Oracle数据库 安装准备 1、安装好操作系统,建议安装图形化2、配置好网络3、上…...
ARP协议相关
把ip地址解析成mac地址这里的mac地址就是路由器的mac地址 免费ARP 源ip和目的ip都是一样的,那怎么让其他人更新arp表呢?? 是因为目标mac是全f,是一个广播报文 如果冲突就是ip一样但是mac又不一样 代理ARP pc1和pc4是在同一个子网…...
Github 2024-06-14 开源项目日报Top10
根据Github Trendings的统计,今日(2024-06-14统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量JavaScript项目2Python项目2非开发语言项目2TypeScript项目1Dart项目1Rust项目1Lua项目1Java项目1Jupyter Notebook项目1从零开始构建你喜爱的技…...
记录AE快捷键(持续补充中。。。)
记录AE快捷键 快捷键常用快捷键图层快捷键工具栏图层与属性常用指令视图菜单时间轴常规快捷键项目首选项功能摄像机操作 常用操作导入AI/PS工程文件加选一个关键参数快速回到上下一帧隐藏/显示图层关键帧拉长缩短关键帧按着鼠标左键不松手,在秒表那一列往下移动会都…...
基于springboot实现问卷调查系统项目【项目源码+论文说明】计算机毕业设计
基于springboot实现问卷调查系统演示 摘要 传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,问卷信息因为其管理内容繁杂,管理数…...
React@16.x(29)useRef
目录 1,介绍2,和 React.createRef() 的区别3,计时器的问题 目前来说,因为函数组件每次触发更新时,都会重新运行。无法像类组件一样让一些内容保持不变。 所以才出现了各种 HOOK 函数:useState,u…...
无人机的力量——在民用方面的应用
无人机在民用方面的应用广泛且多样化,以下是对其应用的详细介绍: 影视航拍: 无人机航拍影像具有高清晰、大比例尺、小面积、高视角的优点,特别适合获取带状地区航拍影像(如公路、铁路、河流、水库、海岸线等ÿ…...
探索档案未来,尽在ARCHE-2024
2024年第三届上海国际智慧档案展览会暨高峰论坛(ARCHE-2024)将于2024年6月19日至21日在上海跨国采购会展中心隆重举行。深圳市铨顺宏科技有限公司应邀参展,将以全新形象盛装亮相,展示其在档案管理领域的最新技术和解决方案。 ARC…...
Maven 核心插件 maven-clean-plugin 使用详解
在软件开发中,构建和管理项目的复杂性随着代码量和依赖的增加而不断提升。Maven作为一个强大的构建工具,简化了这一过程,并通过其插件机制提供了丰富的功能。其中,maven-clean-plugin 是Maven的核心插件之一,它在项目的…...
金融数据中心布线运维管理解决方案
金融行业的核心业务,如交易、支付、结算等,对网络的依赖程度极高。布线作为网络基础设施的重要组成部分,其稳定性和可靠性直接关系到业务的连续运行。因此,良好的布线管理能够确保网络系统的稳定运行,减少因网络故障导…...
C++初学者指南第一步---2. Hello world
C初学者指南第一步—2. Hello world 目录 C初学者指南第一步---2. Hello world1.源文件 “Hello.cpp”2.编译hello.cpp3.术语4.编译器标志5.不要使用 “using namespace std;” ! 1.源文件 “Hello.cpp” #include <iostream> // our first program int main…...
gitLab批量下载有权限的项目
前言 参考 https://www.jianshu.com/p/b3d4e5cee835 适用于git私服拉取个人所涉及权限的代码,方便有多个项目权限的人快速拉取自己所有权限的代码。 默认生成目录结构与gitlab一致 步骤一:获取权限你的代码权限文件d 从gitlab私服生成所有你有权限的代码信息 …...
解决 kali 中使用 vulhub 拉取不到镜像问题
由于默认情况下,访问的镜像是国外的,而从 2023 年开始,docker 的镜像网站就一直访问不了,所以我们可以把镜像地址改成国内的阿里云镜像地址。 1、在 cd /etc/docker/目录下创建或修改daemon.json文件 sudo touch daemon.json 2、在…...
CSS3 简介
CSS3 简介 CSS3,即层叠样式表的第三代,是网页设计和开发中不可或缺的技术之一。它为HTML元素提供了更加丰富和灵活的样式定义,使得网页不仅结构清晰,而且外观精美、交互性强。CSS3继承了CSS2的基本特性,并引入了许多新…...
springboot事务管理的机制是什么
SpringBoot的事务管理机制实质上是基于Spring框架的事务处理机制。其主要目的是确保一系列数据库操作要么全部成功,要么全部失败(回滚),从而维护数据的完整性和一致性。 SpringBoot事务管理遵循ACID四大特性: 1、原子…...
Linux下tar命令解压缩
tar 命令是 Unix 和 Linux 系统中用来创建归档文件以及提取归档文件的工具。它通常用于备份文件或将多个文件和目录打包成一个单独的归档文件。默认情况下,tar 不会对文件进行压缩,但可以通过结合其他压缩工具(如 gzip 或 bzip2)来…...
当财政支持减弱时,国有企业如何实现降本增效?
随着市场环境的不断变化和上级市场化政策要求的不断推进,部分国有企业面临着双重压力,一方面,市场的快速变革要求企业不断创新、提升竞争力;另一方面,在响应上级市场化转型的号召下,财政支持的减弱成为了许…...
大模型「训练」与「微调」概念详解【6000字长文】
本文你将学到什么 1、大模型预训练与微调的基本流程 2、预训练、训练、后期预训练、微调的区别 3、大模型训练与微调的一些概念,如: Post-pretrain、SFT、RLHF、模型对齐、Lora、Q-Lora、大模型量化、微调指标、微调参数、大模型评测指标 预训练与微…...
JVM 垃圾回收器
一、垃圾回收器类型 如果说垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体 实现。下图展示了7种作用于不同分代的收集器,其中用于回收新生代的收集器 包括Serial、PraNew、Parallel Scavenge,回收老年代的收集器包括Seri…...
Spring IOC 容器的构建流程?
Spring loc (Inversion of Control) 是一种设计模式,其中对象的创建和依赖关系由框架管理,而不是由应用程序直接管理。Spring loc容器是Spring框架的核心,它使用loC模式来管理应用程序中的对象 Spring loC容器的构建过程如下: 1.配置元数据…...
官方文档 搬运 MAXMIND IP定位 mysql导入 简单使用
官方文档地址: 官方文档 文件下载 1. 导入mysql可能报错 Error Code: 1290. The MySQL server is running with the --secure-file-priv option so it cannot execute this statement 查看配置 SHOW GLOBAL VARIABLES LIKE %secure%;secure_file_priv 原来…...
PHP入门教程1:PHP的基础概念和基本语法
本文将从基础开始,介绍PHP的基础概念和基本语法。 PHP简介环境搭建基本语法变量和常量数据类型操作符常见错误和调试方法 1. PHP简介 PHP,全称是 “PHP: Hypertext Preprocessor”,是一种开源的通用脚本语言,尤其适用于Web开发…...
网站怎么做app吗/关键词优化资讯
2019独角兽企业重金招聘Python工程师标准>>> 1.端口号,链接在 application 中更改 2.链接名字--项目---web-寻找 转载于:https://my.oschina.net/u/3717819/blog/1801728...
做移动类网站的书推荐/免费自学电商教程
一、题目 演示示例: 二、测试代码 class Solution {public boolean hasGroupsSizeX(int[] deck) {boolean flagfalse;HashMap<Integer,Integer> mapnew HashMap<>();if(deck.length<2)//数组长度小于2直接返回false{return false;}else{for(int i…...
建设雅马哈官方网站/全自动引流推广软件
今天给大家分享一个轻量级Vue.js全屏滚动进度条组件VueScrollProgress。vue-scroll-progress 一款基于vue.js构建的页面滚动进度条组件,非常小巧,GZIP压缩后不到1KB。安装$ npm i vue-scroll-progress -S也支持通过CDN引入使用。引入组件// 在main.js中引…...
80 wordpress/营销推广渠道有哪些
Lora 数据发送与接收 预计到2025年,我们将有250亿台设备连接到互联网。 相当于今天的地球人口多三倍。 随着物联网和工业4.0的概念,互联车辆和智能城市的迅速普及,这种情况最有可能发生。 我们已经有少数无线协议,如BLE、Wi-Fi、蜂窝等,但是这些技术对于IoT传感器节点而言…...
北京商地网站建设公司/微软优化大师
SimpleAdapter是ArrayList和 ListView的桥梁。这个ArrayList里边的每一项都是一个Map<String,?>类型。 ArrayList当中的每一项 Map对象都和ListView里边的每一项进行数据绑定一一对应。 SimpleAdapter的构造函数: SimpleAdapter(Context context, List<?…...
网站开发背景怎么写/百度外推排名代做
HM9921/HM9924泛海微原厂2.5A内置MOS降压恒流IC支持PWM调光 HM9921/HM9924 是一款高效率,稳定可靠 的高亮度 LED 灯恒流驱动控制芯片,内置 高精度比较器,固定关断时间控制电路, 恒流驱动电路等,特别适合大功率、多个…...