GPU 內核虛擬化 - 原理篇
cgpu
目前市面上大部分文章都只提了一下通過攔截驅動 ioctl、mmap、read、write 接口的調用來實現內核虛擬化,但是具體怎麼實現沒有描述。
內核虛擬化是從阿里最先有的,這篇 ** 文章 [1]** 對 cgpu 是分析的最深入的。也提供了一個之前版本的代碼:https://github.com/lvmxh/cgpu.git
由於代碼裏面的核心部分 cgpu.o 沒有開源,所以只能分析一些非核心的實現。
內核攔截
首先我們要知道設備是如何被調用的,設備在 Linux 中一個文件描述符,所以應用程序就是通過系統調用 open、read、write、mmap、ioctl 等等操作來直接操作設備文件描述符,比如 /dev/nvidia0 .
在內核空間中 Linux 有一個驅動程序的結構體定義 file_operations ,它會把系統調用的 open、read 等等操作都通過驅動程序來實現。
有了核心原理我們就可以去分析 cgpu 這個項目了。那具體想知道在調用 nvidia 設備的過程中執行了哪些系統調用,可以使用 strace 命令去獲取。
通過如下的命令可以獲取執行 nvidia-smi 命令過程中的系統調用。
$ strace -e trace=mmap nvidia-smi
$ strace -e trace=ioctl nvidia-smi
$ strace nvidia-smi
cgpu 核心框架
cgpu 中有三個文件 cgpu-km.c 和 cgpu-procfs.c 和 os-interface.c ,核心入口是 cgpu-km.c, 因爲它提供了 module_init 和 module_exit。
cgpu-km.c 文件分析
核心的就是我們先看它聲明的驅動程序接口,主要定義如下的操作。在 cgpu 的最新版依然是隻實現瞭如下幾個函數,說明實現這個函數就可以實現虛擬化了。
static struct file_operations cgpu_km_fops = {
.owner = THIS_MODULE,
.poll = cgpu_km_poll,
.unlocked_ioctl = cgpu_km_unlocked_ioctl,
.compat_ioctl = cgpu_km_compat_ioctl,
.mmap = cgpu_km_mmap,
.open = cgpu_km_open,
.release = cgpu_km_close,
};
上面涉及到的幾個函數都沒有源代碼定義,可以通過 objdump -t cgpu.o 命令來查看都是定義在 cgpu.o 文件中的。
下面來分析驅動程序被加載的時候都幹了些什麼?
static int __init cgpu_km_init(void)
{
int ret = 0;
int num = 0;
# 這個函數也是定義 cgpu.o 裏面的
num = cgpu_initialize();
# 這裏是註冊字符設備,名字是 cgpu-km
ret = register_chrdev(0, "cgpu-km", &cgpu_km_fops);
...
cgpu_major = ret;
# 這個函數是在 cgpu-procfs.c 文件中定義的,我們稍後分析。
ret = cgpu_km_procfs_init(num);
if (ret) {
pr_err("failed to init cgpu km procfs\n");
unregister_chrdev(cgpu_major, "cgpu-km");
}
return ret;
}
下面是驅動被卸載的時候執行的清理邏輯;
static void __exit cgpu_km_exit(void)
{
# 同樣是定義在 cgpu.o 文件中
cgpu_finalize();
# 在 cgpu-procfs.c 文件中定義
cgpu_km_procfs_deinit();
# 移除cgpu-km的字符設備註冊
unregister_chrdev(cgpu_major, "cgpu-km");
}
cgpu-procfs.c 文件分析
cgpu 提供內核態參數設置的接口是 procfs,並不是 sysfs。
os-interface.c 文件分析
這個文件裏面通過內核線程和 queue 實現的 cGPU 調度算法;來控制一張卡上的多任務切換。
編譯
目前我在 ubuntu22.04 版本下成功編譯了這個項目,因爲我使用的是高內核的版本,所以需要修改代碼裏面一些過時的系統調用,可以直接使用我修改過的。
https://github.com/lengrongfu/study-demo/blob/main/gpu/cgpu/README.md
參考資料
[1] 文章:
https://www.cnblogs.com/shaohef/p/13616687.html
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/itLrrVyQ4AnJhFjWpQ1m5g