首页 > 解决方案 > 从 ioctl 调用 DRM_IOCTL_MODE_GETRESOURCES 返回零连接器计数

问题描述

我的目标是弄清楚如何进行快速屏幕捕获。一种方法是利用 GPU 抓取帧(然后在 GPU 上快速对其进行编码)。

我正在尝试在 Linux 上执行此操作,并使用 DRM/KMS 等低级 API 来实现此目的。

目前,我没有取回任何连接器。

跑步:Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-1044-aws x86_64)

C++ 代码:

#include <stdio.h>
#include <fcntl.h>
#include <drm/drm.h>
#include <drm/drm_mode.h>
#include <sys/ioctl.h>
#include <cstdint>
#include <stdint.h>

using namespace std;

int main() {

    int dri_fd = open("/dev/dri/card0", O_RDWR);
    printf("fd: %d\n", dri_fd);

    if (dri_fd == -1) {
        printf("Could not open card0\n");
        return -1;
    }

    ioctl(dri_fd, DRM_IOCTL_SET_MASTER, 0); // We only need to be "master" to do the actual KMS mode setting
    drm_mode_card_res res = {0};
    ioctl(dri_fd, DRM_IOCTL_MODE_GETRESOURCES, &res);
    printf("FB Count: %d\n", res.count_fbs);
    printf("Connector Count: %d\n", res.count_connectors);
    printf("CRTC Count: %d\n", res.count_crtcs);
    printf("Encoder Count: %d\n", res.count_encoders);

    uint64_t fb_buf[10] = {0};
    uint64_t crtc_buf[10] = {0};
    uint64_t conn_buf[10] = {0};
    uint64_t enc_buf[10] = {0};

    res.fb_id_ptr = (uint64_t)fb_buf; // Frame buffer
    res.crtc_id_ptr = (uint64_t)crtc_buf; // A CRTC represents the overall display pipeline.
    res.connector_id_ptr = (uint64_t)conn_buf; // In DRM connectors are the general abstraction for display sinks, and include als fixed panels or anything else that can display pixels in some form.
    res.encoder_id_ptr = (uint64_t)enc_buf; // An encoder takes pixel data from a CRTC and converts it to a format suitable for any attached connector.

    // Get resource IDs
    ioctl(dri_fd, DRM_IOCTL_MODE_GETRESOURCES, &res);

    return 0;
}

输出:

:~$ sudo ./capture
fd: 3
FB Count: 0
Connector Count: 0
CRTC Count: 0
Encoder Count: 0

我的期望是连接器计数或 FB 计数将返回非零值,因为我的 M60 NVIDIA GPU 似乎连接到 X11/Gnome:

ubuntu:~$ nvidia-smi
Fri Aug  2 00:59:01 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 430.30       Driver Version: 430.30       CUDA Version: 10.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla M60           Off  | 00000000:00:1E.0 Off |                    0 |
| N/A   28C    P8    14W / 150W |    141MiB /  7618MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0      3255      G   /usr/lib/xorg/Xorg                            57MiB |
|    0      3286      G   /usr/bin/gnome-shell                          82MiB |
+-----------------------------------------------------------------------------+

其他相关诊断信息:

ubuntu:~$ cat /etc/modprobe.d/nvidia.conf
options nvidia-drm modeset=1


ubuntu:~$ cat /etc/modprobe.d/blacklist.conf
# This file lists those modules which we don't want to be loaded by
# alias expansion, usually so some other driver will be loaded for the
# device instead.

# evbug is a debug tool that should be loaded explicitly
blacklist evbug

# these drivers are very simple, the HID drivers are usually preferred
blacklist usbmouse
blacklist usbkbd

# replaced by e100
blacklist eepro100

# replaced by tulip
blacklist de4x5

# causes no end of confusion by creating unexpected network interfaces
blacklist eth1394

# snd_intel8x0m can interfere with snd_intel8x0, doesn't seem to support much
# hardware on its own (Ubuntu bug #2011, #6810)
blacklist snd_intel8x0m

# Conflicts with dvb driver (which is better for handling this device)
blacklist snd_aw2

# Causes trackpads to stop working on Lenovo 11e 2nd gen (Ubuntu: #1802135)
# and Lenovo x240 to hang on boot (Ubuntu: #1802689)
blacklist i2c_i801

# replaced by p54pci
blacklist prism54

# replaced by b43 and ssb.
blacklist bcm43xx

# most apps now use garmin usb driver directly (Ubuntu: #114565)
blacklist garmin_gps

# replaced by asus-laptop (Ubuntu: #184721)
blacklist asus_acpi

# low-quality, just noise when being used for sound playback, causes
# hangs at desktop session start (Ubuntu: #246969)
blacklist snd_pcsp

# ugly and loud noise, getting on everyone's nerves; this should be done by a
# nice pulseaudio bing (Ubuntu: #77010)
blacklist pcspkr

# EDAC driver for amd76x clashes with the agp driver preventing the aperture
# from being initialised (Ubuntu: #297750). Blacklist so that the driver
# continues to build and is installable for the few cases where its
# really needed.
blacklist amd76x_edac
blacklist vga16fb
blacklist nouveau
blacklist rivafb
blacklist nvidiafb
blacklist rivatv


ubuntu:~$ lsmod
Module                  Size  Used by
nvidia_drm             45056  3
nvidia_modeset       1110016  3 nvidia_drm
nvidia              18796544  218 nvidia_modeset
drm_kms_helper        167936  1 nvidia_drm
drm                   393216  6 drm_kms_helper,nvidia_drm
i2c_core               73728  3 drm_kms_helper,nvidia,drm
fb_sys_fops            16384  1 drm_kms_helper
syscopyarea            16384  1 drm_kms_helper
sysfillrect            16384  1 drm_kms_helper
sysimgblt              16384  1 drm_kms_helper
ipmi_devintf           20480  0
ipmi_msghandler        53248  2 ipmi_devintf,nvidia
serio_raw              16384  0
sch_fq_codel           20480  9
ib_iser                49152  0
rdma_cm                61440  1 ib_iser
iw_cm                  45056  1 rdma_cm
ib_cm                  53248  1 rdma_cm
ib_core               225280  4 rdma_cm,iw_cm,ib_iser,ib_cm
iscsi_tcp              20480  0
libiscsi_tcp           20480  1 iscsi_tcp
libiscsi               53248  3 libiscsi_tcp,iscsi_tcp,ib_iser
scsi_transport_iscsi    98304  3 iscsi_tcp,ib_iser,libiscsi
parport_pc             36864  0
ppdev                  20480  0
lp                     20480  0
parport                49152  3 parport_pc,lp,ppdev
ip_tables              28672  0
x_tables               40960  1 ip_tables
autofs4                40960  2
btrfs                1126400  0
zstd_compress         163840  1 btrfs
raid10                 53248  0
raid456               143360  0
async_raid6_recov      20480  1 raid456
async_memcpy           16384  2 raid456,async_raid6_recov
async_pq               16384  2 raid456,async_raid6_recov
async_xor              16384  3 async_pq,raid456,async_raid6_recov
async_tx               16384  5 async_pq,async_memcpy,async_xor,raid456,async_raid6_recov
xor                    24576  2 async_xor,btrfs
raid6_pq              114688  4 async_pq,btrfs,raid456,async_raid6_recov
libcrc32c              16384  1 raid456
raid1                  40960  0
raid0                  20480  0
multipath              16384  0
linear                 16384  0
crct10dif_pclmul       16384  0
crc32_pclmul           16384  0
ghash_clmulni_intel    16384  0
pcbc                   16384  0
aesni_intel           188416  0
aes_x86_64             20480  1 aesni_intel
crypto_simd            16384  1 aesni_intel
glue_helper            16384  1 aesni_intel
cryptd                 24576  3 crypto_simd,ghash_clmulni_intel,aesni_intel
ena                    94208  0


ubuntu:~$ dmesg | grep -i NV
[    0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-4.15.0-1044-aws root=UUID=8abb4f2d-c7e0-4daf-80b5-24e1c814cf55 ro rdblacklist=nouveau console=tty1 console=ttyS0 nvme_core.io_timeout=4294967295
[    0.000000] Kernel command line: BOOT_IMAGE=/boot/vmlinuz-4.15.0-1044-aws root=UUID=8abb4f2d-c7e0-4daf-80b5-24e1c814cf55 ro rdblacklist=nouveau console=tty1 console=ttyS0 nvme_core.io_timeout=4294967295
[    0.616004] ACPI: Added _OSI(Linux-Lenovo-NV-HDMI-Audio)
[    2.324353] rtc_cmos 00:02: alarms up to one day, 114 bytes nvram, hpet irqs
[    7.467294] nvidia: loading out-of-tree module taints kernel.
[    7.467301] nvidia: module license 'NVIDIA' taints kernel.
[    7.476833] nvidia: module verification failed: signature and/or required key missing - tainting kernel
[    7.488128] nvidia-nvlink: Nvlink Core is being initialized, major device number 243
[    7.489962] nvidia 0000:00:1e.0: vgaarb: changed VGA decodes: olddecodes=io+mem,decodes=none:owns=io+mem
[    7.490503] NVRM: loading NVIDIA UNIX x86_64 Kernel Module  430.30  Mon Jun 10 05:04:34 CDT 2019
[    7.511462] nvidia-modeset: Loading NVIDIA Kernel Mode Setting Driver for UNIX platforms  430.30  Mon Jun 10 04:38:05 CDT 2019
[    7.514021] [drm] [nvidia-drm] [GPU ID 0x0000001e] Loading driver
[    8.790628] [drm] Initialized nvidia-drm 0.0.0 20160202 for 0000:00:1e.0 on minor 0
[  227.400569] [drm] [nvidia-drm] [GPU ID 0x0000001e] Unloading driver
[  227.400786] NVRM: Persistence mode is deprecated and will be removed in a future release. Please use nvidia-persistenced instead.
[  227.585668] nvidia-modeset: Unloading
[  227.876830] nvidia-nvlink: Unregistered the Nvlink Core, major device number 243
[  237.950918] nvidia-nvlink: Nvlink Core is being initialized, major device number 243
[  237.952092] nvidia 0000:00:1e.0: vgaarb: changed VGA decodes: olddecodes=none,decodes=none:owns=io+mem
[  237.952418] NVRM: loading NVIDIA UNIX x86_64 Kernel Module  430.30  Mon Jun 10 05:04:34 CDT 2019
[  237.955126] nvidia-modeset: Loading NVIDIA Kernel Mode Setting Driver for UNIX platforms  430.30  Mon Jun 10 04:38:05 CDT 2019
[  237.956384] [drm] [nvidia-drm] [GPU ID 0x0000001e] Loading driver
[  239.061266] [drm] Initialized nvidia-drm 0.0.0 20160202 for 0000:00:1e.0 on minor 0

标签: c++linuxgraphicslinux-kernelnvidia

解决方案


推荐阅读