Linux drm_syncobj機制原理與應用方式
1. 概念
1.1 什么是 drm_syncobj
DRM Sync Object(同步對象,簡稱 syncobj)是 Linux DRM(Direct Rendering Manager)子系統中用于 GPU 命令同步的內核抽象。
syncobj 的設計初衷是為用戶空間提供一種高效、靈活的 GPU 任務同步原語,主要用于顯卡驅動和用戶空間(如 Vulkan、OpenCL、OpenGL 等)之間的同步需求。
syncobj 的核心作用是包裝一個指向 dma_fence 結構體的指針(可能為 NULL),通過 ioctl 接口,用戶空間可以創(chuàng)建、銷毀、導入、導出、信號、重置、等待等操作 syncobj,從而實現 GPU 命令流的精細同步。
1.2 設計目標
- 跨進程/跨驅動共享:syncobj 可通過 fd 句柄在進程間傳遞,實現多進程/多驅動同步。
- 支持二元與時間線語義:既可作為簡單的“signaled/unsignal”二元同步原語,也可作為時間線(timeline)同步原語,支持多點同步。
- 高效用戶空間接口:通過一組 ioctl,用戶空間可靈活操作 syncobj,滿足 Vulkan 等現代圖形 API 的同步需求。
drm_syncobj是為用戶空間設計的,因此內核自身不會使用該結構體,只有各家的GPU驅動才會使用。
1.3 主要數據結構
| 結構體名稱 | 作用說明 |
|---|---|
| struct drm_syncobj | 同步對象的核心結構,包含 fence 指針、回調鏈表、事件鏈表、鎖等。 |
| struct dma_fence | 底層同步原語,表示 GPU 命令完成的信號。 |
| struct dma_fence_chain | 時間線模式下的鏈式 fence,支持多點同步。 |
| struct syncobj_wait_entry | 用于等待的輔助結構。 |
| struct syncobj_eventfd_entry | 用于事件通知的輔助結構。 |
2. 原理分析
2.1 同步機制原理
2.1.1 二元同步對象
在二元模式下,syncobj 通過維護一個可替換的 fence 指針實現同步狀態(tài)管理。
該設計充分利用了 dma_fence 的單向狀態(tài)特性(不可逆的"已信號"狀態(tài),dma_fence的單向狀態(tài)轉換決定了的單個dma_fence是短命的),通過動態(tài)創(chuàng)建并替換 fence 對象實現狀態(tài)重置。
- 信號操作:驅動創(chuàng)建新的已信號
dma_fence替換原對象。 - 重置操作:驅動創(chuàng)建新的未信號
dma_fence替換原對象。
2.1.2 時間線同步對象
- 時間線模式下,syncobj 維護一個
dma_fence_chain,每個鏈節(jié)點代表一個時間點(seqno)。 - GPU 驅動可在任意時間點插入新的 fence,實現多點同步。
- 用戶空間可針對任意時間點進行信號、等待、查詢等操作。
2.1.3 等待機制
- 主機側等待:通過
DRM_IOCTL_SYNCOBJ_WAIT或DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT,用戶空間可等待一個或多個 syncobj 的 fence 被信號。支持等待全部或任意一個、超時、deadline、等待 fence 出現等多種模式。 - 事件通知:通過 eventfd 機制,用戶空間可注冊事件,當 syncobj 被信號時,eventfd 被喚醒,便于集成到事件循環(huán)。
2.1.4 導入/導出機制
- fd 句柄導入/導出:syncobj 可導出為 fd,在進程間傳遞,所有 fd 共享同一個底層 syncobj。
- sync_file 導入/導出:可將 syncobj 當前 fence 導出為 sync_file,或從 sync_file 導入 fence 到 syncobj。sync_file 是 Linux 通用的同步文件描述符,便于與其他子系統(如 dma-buf)集成。
2.2 典型流程
- 用戶空間通過 ioctl 創(chuàng)建 syncobj,獲得 handle 或 fd。
- GPU 驅動在提交命令時,將 fence 綁定到 syncobj。
- a. 用戶空間可通過 ioctl 等待 syncobj 被信號,或查詢其狀態(tài)。b. GPU執(zhí)行完命令后,發(fā)中斷,中斷處理中singal syncobj。a和b兩個過程是同時進行的,看哪個先完成。
- syncobj 可在進程間傳遞,實現跨進程同步。
- 時間線模式下,用戶空間和驅動可在任意時間點操作 syncobj,實現復雜同步場景。
這個典型使用流程是理解syncobj的關鍵,記住一點:syncobj是用戶空間使用的。
3. 實現
syncobj 支持如下基本操作:
| 操作類型 | 說明 |
|---|---|
| 創(chuàng)建與銷毀 | 分配和釋放同步對象資源 |
| 信號與重置 | 設置同步對象為已完成或未完成狀態(tài) |
| 等待 | 阻塞或非阻塞地等待同步對象變?yōu)橐淹瓿蔂顟B(tài) |
| 導入與導出 | 將同步對象的狀態(tài)在進程間傳遞,實現跨進程同步 |
| timeline 操作 | 部分驅動支持 timeline syncobj,可以表示多個時間點的同步狀態(tài) |
3.1 接口分類和功能
| 分類 | 主要接口/函數名 | 功能說明 |
|---|---|---|
| 創(chuàng)建與銷毀 | drm_syncobj_create | 分配并初始化 syncobj,支持初始信號狀態(tài)(SIGNALED) |
| drm_syncobj_destroy | 釋放 syncobj,清理所有引用和資源 | |
| 導入與導出 | drm_syncobj_get_handle / drm_syncobj_get_fd | 將 syncobj 導出為 handle 或 fd |
| drm_syncobj_handle_to_fd / drm_syncobj_fd_to_handle | fd 與 handle 互轉,支持跨進程共享 | |
| drm_syncobj_import_sync_file_fence / drm_syncobj_export_sync_file | 與 sync_file 互操作,便于與 dma-buf 等子系統集成 | |
| 信號與重置 | drm_syncobj_replace_fence | 替換 syncobj 的 fence,實現信號或重置 |
| drm_syncobj_assign_null_handle | 分配一個已信號的 stub fence,實現“信號”操作 | |
| drm_syncobj_signal_ioctl / drm_syncobj_reset_ioctl | 用戶空間 ioctl 接口,批量信號或重置 syncobj | |
| 時間線操作 | drm_syncobj_add_point | 在時間線 syncobj 上添加新的時間點(fence_chain) |
| drm_syncobj_transfer_to_timeline / drm_syncobj_transfer_to_binary | 在不同 syncobj 間轉移時間點或 fence,實現復雜同步場景 | |
| drm_syncobj_timeline_signal_ioctl | 用戶空間 ioctl,批量信號時間線上的多個點 | |
| drm_syncobj_query_ioctl | 查詢時間線 syncobj 的狀態(tài),支持查詢最后提交點或最后信號點 | |
| 等待與事件通知 | drm_syncobj_array_wait_timeout | 核心等待實現,支持多種等待模式(全部、任意、超時、deadline等) |
| drm_syncobj_eventfd_ioctl | 注冊 eventfd,當 syncobj 被信號時喚醒用戶空間 | |
| dma_fence_add_callback | fence 信號時的喚醒和事件通知回調機制 | |
| 內存與引用管理 | kref 引用計數機制 | syncobj 通過引用計數管理生命周期,確保多進程/多 fd 安全 |
| 嚴格引用管理 | 所有導入/導出、等待、事件等操作均嚴格管理引用,防止資源泄漏 |
3.2 關鍵代碼分析
這部分專門出一篇博文介紹,還在編寫中....
4. 為什么設計 drm_syncobj
下面是 drm_syncobj 與 dma_resv、sync_file 的對比分析,并說明 drm_syncobj 的設計初衷和優(yōu)勢。
| 對比項 | dma_resv(內核使用) | sync_file | drm_syncobj(設計初衷與優(yōu)勢) |
|---|---|---|---|
| 主要用途 | 內核對象,管理 dma-buf 的同步(讀/寫 fence) | 用戶空間同步文件,導出/傳遞 fence | 用戶空間可管理的同步對象,專為 GPU/Vulkan 設計 |
| 用戶空間接口 | 無直接接口,驅動內部使用 | 通過 fd 傳遞,支持 epoll/select | 豐富 ioctl 接口,支持創(chuàng)建、導入、導出、信號、等待 |
| 跨進程/驅動 | 僅限 dma-buf 相關驅動間 | 可跨進程傳遞,但只封裝單個 fence | 可跨進程/驅動共享,支持 timeline 多點同步 |
| 時間線支持 | 不支持,只有讀/寫二元 fence | 不支持,單一 fence | 支持 timeline fence_chain,滿足 Vulkan timeline |
| 事件通知 | 無 | 支持 eventfd | 支持 eventfd,且可針對 timeline 任意點 |
| 資源管理 | 內核自動管理 | 用戶空間 fd 管理,生命周期與 fd 綁定 | 引用計數(kref),fd/handle均可安全管理 |
| 設計初衷 | dma-buf 內核同步,面向驅動開發(fā) | 通用 fence 導出/傳遞,面向用戶空間 | 面向 GPU/Vulkan 用戶空間同步,靈活高效 |
| 典型應用場景 | 顯存緩沖區(qū)同步,驅動內部 | 用戶空間異步等待、跨進程同步 | Vulkan fence/semaphore、跨進程/驅動 GPU 協作 |
- 滿足現代圖形 API(如 Vulkan)的同步需求:Vulkan 需要 timeline semaphore、跨進程/驅動同步、事件通知等高級功能,dma_resv/sync_file 無法滿足。
- 用戶空間可控:drm_syncobj 提供豐富的 ioctl 接口,用戶空間可靈活創(chuàng)建、管理、導入、導出、等待、信號同步對象。
- 支持 timeline fence:drm_syncobj 支持多點同步,適配 Vulkan timeline semaphore,遠超 sync_file 的單點能力。
- 跨進程/驅動協作:通過 fd/handle 機制,drm_syncobj 可在多進程、多驅動間安全共享和同步。
- 高效事件通知:集成 eventfd,便于用戶空間異步編程和事件循環(huán)。
drm_syncobj 是為現代 GPU 用戶空間同步場景量身定制的內核抽象,彌補了 dma_resv/sync_file 在靈活性、擴展性和用戶空間接口上的不足。
用戶態(tài)的應用接口封裝在libdrm中,具體實現分析見:Linux libdrm 中 drm_syncobj的實現原理。這兩篇對照著看,基本上是一一對應。
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
linux之SSH連接WSL2本地環(huán)境的操作方式
這篇文章主要介紹了linux之SSH連接WSL2本地環(huán)境的操作方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-05-05
Ubuntu18.04一次性升級Python所有庫的方法步驟
這篇文章主要介紹了Ubuntu18.04一次性升級Python所有庫的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-01-01
如何利用多核CPU來加速你的Linux命令(GNU Parallel)
這篇文章主要介紹了如何利用多核CPU來加速你的Linux命令(GNU Parallel),小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01
Linux系統下使用rpm方式安裝最新mysql5.7.17完整步驟
這篇文章主要介紹了Linux系統下使用rpm方式安裝最新mysql5.7.17完整步驟,需要的朋友可以參考下2017-01-01

