如何在C语言中获取Linux主机的GPU信息?
在Linux下用纯C获取GPU信息的可行方案
完全可行,不需要依赖lshw的输出解析,以下是几种实用的实现方式,按通用性和针对性分类:
1. 跨厂商通用方案:libdrm
libdrm是Linux DRM(Direct Rendering Manager)的用户空间库,能直接与GPU驱动交互,获取硬件基础信息,支持NVIDIA、AMD、Intel等主流厂商的GPU。
示例代码
#include <drm/drm.h> #include <drm/drm_mode.h> #include <stdio.h> #include <stdlib.h> int main() { drmDevicePtr devices[64]; int dev_count = drmGetDevices(devices, 64, 0); if (dev_count < 0) { perror("Failed to get DRM devices"); return EXIT_FAILURE; } for (int i = 0; i < dev_count; i++) { drmDevicePtr dev = devices[i]; printf("=== GPU %d ===\n", i); printf("品牌/型号: %s\n", dev->device_name); printf("PCI厂商ID: 0x%04x\n", dev->businfo.pci->vendor_id); printf("PCI设备ID: 0x%04x\n", dev->businfo.pci->device_id); // 查询显存大小 uint64_t vram_size; if (drmGetClientCap(dev->fd, DRM_CLIENT_CAP_VRAM, &vram_size) == 0) { printf("总显存: %lu MB\n", vram_size / (1024 * 1024)); } drmFreeDevice(&dev); } return EXIT_SUCCESS; }
编译与运行
gcc -o gpu_info_drm gpu_info_drm.c -ldrm sudo ./gpu_info_drm # 或加入video组以无需root权限
2. NVIDIA专属方案:NVML
NVIDIA Management Library(NVML)是官方提供的管理库,能获取NVIDIA GPU的详细信息(包括显存、温度、利用率等),可靠性高。
示例代码
#include <nvml.h> #include <stdio.h> #include <stdlib.h> int main() { nvmlReturn_t ret = nvmlInit(); if (ret != NVML_SUCCESS) { fprintf(stderr, "NVML初始化失败: %s\n", nvmlErrorString(ret)); return EXIT_FAILURE; } unsigned int dev_count; ret = nvmlDeviceGetCount(&dev_count); if (ret != NVML_SUCCESS) { fprintf(stderr, "获取GPU数量失败: %s\n", nvmlErrorString(ret)); nvmlShutdown(); return EXIT_FAILURE; } for (unsigned int i = 0; i < dev_count; i++) { nvmlDevice_t dev; ret = nvmlDeviceGetHandleByIndex(i, &dev); if (ret != NVML_SUCCESS) { fprintf(stderr, "获取GPU %d句柄失败: %s\n", i, nvmlErrorString(ret)); continue; } char gpu_name[NVML_DEVICE_NAME_BUFFER_SIZE]; ret = nvmlDeviceGetName(dev, gpu_name, NVML_DEVICE_NAME_BUFFER_SIZE); if (ret == NVML_SUCCESS) { printf("=== NVIDIA GPU %d ===\n", i); printf("型号: %s\n", gpu_name); } nvmlMemory_t mem_info; ret = nvmlDeviceGetMemoryInfo(dev, &mem_info); if (ret == NVML_SUCCESS) { printf("总显存: %lu MB\n", mem_info.total / (1024 * 1024)); printf("已用显存: %lu MB\n", mem_info.used / (1024 * 1024)); printf("可用显存: %lu MB\n", mem_info.free / (1024 * 1024)); } // 获取品牌系列 nvmlDeviceAttribute_t brand; ret = nvmlDeviceGetAttribute(dev, NVML_ATTR_GPU_BRAND, &brand); if (ret == NVML_SUCCESS) { const char* brand_str; switch (brand) { case NVML_BRAND_GEFORCE: brand_str = "GeForce"; break; case NVML_BRAND_QUADRO: brand_str = "Quadro"; break; case NVML_BRAND_TESLA: brand_str = "Tesla"; break; default: brand_str = "Unknown"; break; } printf("品牌系列: %s\n", brand_str); } } nvmlShutdown(); return EXIT_SUCCESS; }
编译与运行
需要安装NVIDIA驱动及开发包(如nvidia-ml-dev):
gcc -o gpu_info_nvml gpu_info_nvml.c -lnvidia-ml ./gpu_info_nvml
3. AMD专属方案:ADL
Advanced Display Library(ADL)是AMD官方提供的库,用于获取AMD GPU的硬件信息和控制显示参数。
示例代码
#include <adl/adl.h> #include <stdio.h> #include <stdlib.h> int main() { ADL_CONTEXT_HANDLE context; if (ADL_Main_Control_Create(ADL_Main_Memory_Alloc, 1) != ADL_OK) { fprintf(stderr, "ADL初始化失败\n"); return EXIT_FAILURE; } if (ADL_Main_Control_GetContext(&context) != ADL_OK) { fprintf(stderr, "获取ADL上下文失败\n"); ADL_Main_Control_Destroy(); return EXIT_FAILURE; } int adapter_count; if (ADL_Adapter_NumberOfAdapters_Get(&adapter_count) != ADL_OK) { fprintf(stderr, "获取适配器数量失败\n"); ADL_Main_Control_Destroy(); return EXIT_FAILURE; } for (int i = 0; i < adapter_count; i++) { ADLAdapterInfo adapter_info; if (ADL_Adapter_Info_Get(i, &adapter_info) == ADL_OK) { printf("=== AMD GPU %d ===\n", i); printf("型号: %s\n", adapter_info.strAdapterName); } ADLDisplayMemoryInfo mem_info; if (ADL_Display_MemoryInfo_Get(i, 0, &mem_info) == ADL_OK) { printf("总显存: %lu MB\n", mem_info.ullTotalMemory / (1024 * 1024)); } } ADL_Main_Control_Destroy(); return EXIT_SUCCESS; }
编译与运行
需要安装AMD驱动及ADL开发文件,编译时链接ADL库:
gcc -o gpu_info_adl gpu_info_adl.c -ladl ./gpu_info_adl
4. 无额外库方案:读取sysfs
Linux的sysfs文件系统暴露了硬件的详细信息,无需依赖任何第三方库,直接读取/sys/class/drm/下的文件即可获取GPU信息。
示例代码
#include <stdio.h> #include <dirent.h> #include <string.h> #include <stdlib.h> #define SYSFS_DRM_PATH "/sys/class/drm/" int main() { DIR* drm_dir = opendir(SYSFS_DRM_PATH); if (!drm_dir) { perror("Failed to open DRM sysfs directory"); return EXIT_FAILURE; } struct dirent* entry; while ((entry = readdir(drm_dir)) != NULL) { if (strncmp(entry->d_name, "card", 4) == 0) { char file_path[256]; printf("=== %s ===\n", entry->d_name); // 读取厂商ID snprintf(file_path, sizeof(file_path), "%s%s/device/vendor", SYSFS_DRM_PATH, entry->d_name); FILE* f = fopen(file_path, "r"); if (f) { unsigned int vendor_id; fscanf(f, "%x", &vendor_id); fclose(f); printf("品牌: "); switch (vendor_id) { case 0x10de: printf("NVIDIA\n"); break; case 0x1002: printf("AMD\n"); break; case 0x8086: printf("Intel\n"); break; default: printf("Unknown (0x%04x)\n", vendor_id); break; } } // 读取型号名称 snprintf(file_path, sizeof(file_path), "%s%s/device/name", SYSFS_DRM_PATH, entry->d_name); f = fopen(file_path, "r"); if (f) { char name[256]; fgets(name, sizeof(name), f); fclose(f); name[strcspn(name, "\n")] = '\0'; printf("型号: %s\n", name); } // 读取显存大小 snprintf(file_path, sizeof(file_path), "%s%s/device/mem_info/vram_total", SYSFS_DRM_PATH, entry->d_name); f = fopen(file_path, "r"); if (f) { unsigned long long vram_total; fscanf(f, "%llu", &vram_total); fclose(f); printf("总显存: %llu MB\n", vram_total / (1024 * 1024)); } } } closedir(drm_dir); return EXIT_SUCCESS; }
编译与运行
gcc -o gpu_info_sysfs gpu_info_sysfs.c ./gpu_info_sysfs # 普通用户即可读取
内容的提问来源于stack exchange,提问作者Ar Rakin
相关产品推荐
相关产品推荐

