Linux DRM - 코어 초기화와 드라이버 등록
How Linux DRM comes up: drm_core_init registers major number 226, and a driver such as vkms creates its /dev/dri nodes through drm_dev_init and drm_dev_register in Linux v6.19.
October 27, 2026
Linux DRM - 코어 초기화와 드라이버 등록
Reqruies
- Kernel: Linux v6.19 소스 기준
- 선행 글: Linux DRM 1편 구조와 전체 그림
Introduction
| 편 | 주제 |
|---|---|
| 1편 | 구조와 전체 그림 |
1편에서 DRM의 구조(
drm_driver → drm_device → drm_minor → drm_file)와 장치 노드를 봤습니다. 이 글에서는 그 구조가 코드에서 어떻게 만들어지는지를 두 단계로 따라갑니다. 부팅 때 DRM core가 주 번호 226을 예약하는 것, 그리고 드라이버(여기서는 가상 드라이버 vkms)가 장치를 만들고 /dev/dri/card0, renderD128을 등록하는 것입니다.Code Flow 1: DRM Core Initialization
DRM은 커널이 부팅될 때 한 번 초기화됩니다. 여기서 앞서 본 주 번호 226이 등록됩니다.
drivers/gpu/drm/drm_drv.c - drm_core_init() (L1236-1272)c
소스 drivers/gpu/drm/drm_drv.c L1236-L1272 (Linux v6.19)
drm_sysfs_init()이 /sys/class/drm 클래스를 만들고, register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops)가 /proc/devices의 226 drm 줄을 만듭니다. 이 시점에는 어떤 장치도 없습니다. 주 번호 226 전체를 DRM이 예약하고, 모든 open()을 받는 "stub" 파일 연산 하나를 등록한 것뿐입니다.Code Flow 2: The Driver Registers the Device
이제 드라이버가 나설 차례입니다. vkms로 보겠습니다. 먼저 드라이버가 정의한
drm_driver입니다.drivers/gpu/drm/vkms/vkms_drv.c - vkms_driver (L92-102)c
소스 drivers/gpu/drm/vkms/vkms_drv.c L92-L102 (Linux v6.19)
DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_GEM, 그리고 DEFINE_DRM_GEM_FOPS로 만든 fops가 전부입니다. 이 드라이버를 등록하는 함수는 vkms_create()입니다.drivers/gpu/drm/vkms/vkms_drv.c - vkms_create() (L159-220)c
소스 drivers/gpu/drm/vkms/vkms_drv.c L159-L220 (Linux v6.19)
드라이버 등록 흐름 (vkms 기준)MermaidsequenceDiagram participant D as 드라이버 (vkms_create) participant C as DRM core participant S as sysfs · devtmpfs · udev D->>C: devm_drm_dev_alloc(&vkms_driver) C->>C: drm_dev_init()<br/>drm_minor_alloc(RENDER, PRIMARY)<br/>drm_gem_init() D->>C: drm_vblank_init() D->>C: vkms_modeset_init()<br/>(plane · CRTC · connector 등록) D->>C: drm_dev_register() C->>C: drm_minor_register(RENDER)<br/>drm_minor_register(PRIMARY) C->>S: device_add(minor->kdev) S-->>S: /dev/dri/card0 (226:0)<br/>/dev/dri/renderD128 (226:128)
Step 1: Allocation and Initialization (drm_dev_init)
devm_drm_dev_alloc()은 내부의 devm_drm_dev_init()을 거쳐 drm_dev_init()을 부릅니다. 여기서 driver_features를 보고 minor를 만들고, GEM을 초기화합니다.drivers/gpu/drm/drm_drv.c - drm_dev_init() (L701-796)c
소스 drivers/gpu/drm/drm_drv.c L701-L796 (Linux v6.19)
DRIVER_RENDER가 있으면 render minor를, 항상 primary minor를 만듭니다. minor 하나를 만드는 drm_minor_alloc()은 번호를 뽑고(xa_alloc) sysfs용 struct device(kdev)까지 준비합니다.drivers/gpu/drm/drm_drv.c - drm_minor_alloc() (L142-172)c
소스 drivers/gpu/drm/drm_drv.c L142-L172 (Linux v6.19)
Step 2: Registration (drm_dev_register)
드라이버가 KMS 객체까지 준비하고 나면 drm_dev_register()를 부릅니다. 이 순간부터 유저가 장치를 열 수 있습니다.
drivers/gpu/drm/drm_drv.c - drm_dev_register() (L1056-1126)c
소스 drivers/gpu/drm/drm_drv.c L1056-L1126 (Linux v6.19)
drm_minor_register()가 device_add()로 sysfs에 등록하고, minor 번호 표(xa_store)를 채웁니다. 나중에 open()이 이 표로 minor를 찾습니다.drivers/gpu/drm/drm_drv.c - drm_minor_register() (L174-212)c
소스 drivers/gpu/drm/drm_drv.c L174-L212 (Linux v6.19)
Code Locations
| 단계 | 함수 | 위치 (Linux v6.19) |
|---|---|---|
| 부팅: DRM core 초기화 (주 번호 226 등록) | drm_core_init() | drivers/gpu/drm/drm_drv.c |
| 부팅: stub open (fops 교체) | drm_stub_open() | drivers/gpu/drm/drm_drv.c |
| 드라이버: 장치 할당과 minor 생성 | drm_dev_init() | drivers/gpu/drm/drm_drv.c |
| 드라이버: minor 번호와 sysfs 장치 | drm_minor_alloc() | drivers/gpu/drm/drm_drv.c |
| 드라이버: card%d / renderD%d 이름 | drm_sysfs_minor_alloc() | drivers/gpu/drm/drm_sysfs.c |
| 드라이버: 등록 (/dev/dri 노드 생성) | drm_dev_register() | drivers/gpu/drm/drm_drv.c |
| 드라이버: minor를 sysfs에 등록 | drm_minor_register() | drivers/gpu/drm/drm_drv.c |
Summary
이 Post 에서 확인한 것은 다음과 같습니다.
- core 초기화:
drm_core_init()이 주 번호 226을 등록하고, 모든open()을 받는 stub fops를 둡니다. - 드라이버 등록:
devm_drm_dev_alloc()→drm_dev_init()(minor 번호 할당) →drm_dev_register()→drm_minor_register()→device_add()로/dev/dri/card0,renderD128이 생깁니다.
노드가 생겼으니 이제 유저가 쓸 차례입니다. 다음에는
open()과 ioctl()이 커널 안에서 어떻게 처리되는지 봅니다.