드라이버 소스코드 고객에게 배포 관련하여, 빌드, 및 install정도만 해주는 정도였었다. 이렇게 되면, 고객의 host가 커널 버전이 update가 되면, 모듈이 새로운 커널에 맞게 빌드 되지 않아서, 실행을 하지 못하는 문제가 있었다.
이에, DKMS Debian Package형태로 제작을 하게 되었다.
자동 재빌드: 새로운 커널 버전이 설치되거나, 현재 커널이 업데이트 될때마다, DKMS는 이전에 등록된 커널 모듈 소스 코드를 가져와 새로운 커널 버전에 맞게 다시 빌드 하고 설치하준다. - > 사용자는 커널 업데이트 후에도 드라이버를 수동으로 재설치하거나 컴파일 할 필요 없이 계속 사용할 수 있다.
소스 코드 관리: 모듈의 소스 코드를 /usr/src와 같은 표준화된 위치에 보관하고, DKMS 자체는 /var/lib/dkms 디렉터리에 해당 소스 코드에 대한 참조(심볼릭 링크)와 각 커널 버전별 빌드 결과물(컴파일된 .ko 파일) 및 로그를 체계적으로 관리한다.
이 패키지는 Debian 패키지이므로, 일반적인 Debian 패키지의 디렉터리 구조를 따른다.
패키지의 /debian 디렉터리에는 아래와 같은 파일들이 존재하며, 각각의 역할은 다음과 같다.
rules
패키지 빌드 과정의 핵심 스크립트로, 패키지를 어떻게 제작할지를 정의한다.
빌드 도구(debhelper)가 이 파일을 읽어, 소스 빌드·패키징 절차를 실행한다.
control
패키지의 메타 정보를 담는다.
패키지 이름, 버전, 의존성, 설명 등의 정보를 이 파일에서 정의하며, 배포 및 설치에 필수적이다.
prerm
패키지를 제거할 때, 제거가 시작되기 전에 실행된다.
예: 커널 모듈 언로드, 설정 파일 백업, 사용자 정의 사전 처리 작업 등을 수행한다.
postinst
패키지를 설치한 후 실행된다.
이 파일에는 설치 이후의 추가 작업이 정의된다.
예를 들어:
현재 커널 버전에 맞게 모듈을 빌드하고 install
/etc/modprobe.d 설정 추가
udev 규칙 등 일회성 설정 파일 배포
changelog
패키지의 버전 관리 내역을 기록한다.
버전별 변경사항, 작성자, 배포 일자 등이 포함되며, dpkg나 apt에서 이력을 확인할 수 있다.
패키지 루트에 위치한 dkms.conf는 DKMS 관리에 필수적인 설정 파일이다.
이 파일에는 다음과 같은 내용이 정의된다:
dkms add 시 수행할 설정
dkms build 시 빌드 대상, Makefile 경로 등
dkms install 시 설치 경로, 모듈명, 빌드 후 처리 방식 등
즉, dkms.conf는 DKMS의 전반적인 동작 흐름을 제어하는 핵심 파일이다.
Debian Package를 설치하는 고객은 두 개의 시나리오를 맞이할 수 있다.
1. 패키지 설치
2. 커널 버전 업데이트
이 두개를 구분해서 일어나야 할 일을 구분할 수 있다.
dpkg는 .deb아카이브를 열어 패키지 내의 파일들을 파일 시스템에 복사한다.
debian/rules 파일에 정의된 대로, 드라이버의 소스 코드가 /usr/src/모듈 이름-버전/경로 하위에 복사된다.
핵심: DKMS 패키지의 관리자 스크립트인 prerm, postinst, postrm 등이 /var/lib/dpkg/info/ 디렉토리에 복사된다. ex)/var/lib/dpkg/info/패키지명.postinst
prerm이 먼저 실행(만약 이전 버전이 설치되어 있다면)
만약 이전 버전이 설치되어 있다면, 새 버전 설치 전에 이전 버전의 prerm 스크립트가 실행되어 DKMS 트리에 등록된 이전 모듈을 제거하려고 시도한다.
postinst 스크립트 실행
/var/lib/dpkg/info/모듈 이름/postinst 스크립트가 실행된다.
postinst의 내용은 dkms add, dkms build, dkms install과 더불어, udev 규칙, 모듈 의존성 정보 파일을 작성해주는 내용이 들어간다.
dkms build: 등록된 모듈 소스를 현재 실행 중인 커널 버전에 맞게 빌드한다.
동작: DKMS는 source 링크를 통해 소스 코드를 찾아 빌드를 한다. -> 컴파일 된 모듈 파일(.ko)는 /var/lib/dkms/모듈 이름/버전/module하위에 저장된다.
- dkms.conf 파일도 dkms가 관리하는 var/lib/dkms/모듈 이름/버전/하위로 복사된다.
dkms install: dkms install - -k와 같은 옵션이 없으면, 기본적으로 현재 커널 버전(uname -r)에 대해서만 DKMS가 설치한다.
역할: 빌드된 커널 모듈을 시스템의 /lib/module/커널 버전/updates/dkms/경로로 설치하고 커널 모듈 종속성 정보를 업데이트한다.
동작: 컴파일된 .ko파일을 적절한 커널 모듈 디렉토리로 복사하고, depmod -a 명령을 통해 모듈 종속성을 새로 고침힌다.
결과: 이제 커널이 해당 모듈을 찾아 로드할 수 있게 된다.(modprobe 명령으로 로드 가능)
커널 버전 업데이트가 되었을때는 postinst가 실행되지 않는다. 말 그대로 postinst는 패키지를 설치하고 나서만 실행되기 때문이다.
이때는 dkms install명령어가 실행된다.
이 dkms install의 동작은 dkms.conf에 정의해놓은대로 작동한다.
이것은 패키지를 설치한 이후, 새로운 linux-image가 시스템에 설치되거나 업데이트될 때 발생한다. 동작 과정은 아래와 같다.
dkms의 관리자 파일의 위치: /var/lib/dkms/<module_name>/<module_version>/
위의 경로에 postinst를 비롯한 script와 dkms.conf가 존재하고, /source는 /sr/src/모듈 이름/모듈 버전을 심볼릭 링크한다.
커널 모듈 빌드 경로: /var/lib/dkms/<module_name>/<module_version>/<kernel_version>/x86_64
커널 모듈 최종 Install 경로:/lib/modules/<kernel_version>updates/dkms/
etc/modprobe.conf: 모듈 간 의존성을 정의한 파일이다. 어떤 모듈이 먼저 로드되어야 한다 같은..
depmod -a: 리눅스에서 커널 모듈 간의 의존성을 분석하고, 모듈 종속성 정보를 생성하는 역할을 한다. depmod = dependency modules의 줄임말 -a == all
역할: lib/modules/(uname -r)/modules.dep -> 각 모듈이 의존하는 다른 모듈들의 목록을 저장
modprobe는 depmod가 만든 modules.dep 정보를 참고한다.
시스템 전체 훅 디렉토리: 이 디렉토리는 리눅스 시스템에서 새로운 커널이 설치되거나 업데이트될 때 실행될 모든 스크립트들을 모아두는 중앙 집중식 장소입니다.
커널 패키지의 postinst가 호출: 앞서 설명했듯이, 특정 linux-image-X.Y.Z.deb 패키지가 설치되면, 해당 커널 이미지 패키지에 포함된 postinst 스크립트가 실행됩니다.
콜링 스크립트: 바로 이 커널 이미지 패키지의 postinst 스크립트가 /etc/kernel/postinst.d/ 디렉토리를 스캔하여 그 안에 있는 모든 실행 가능한 스크립트들을 순서대로 호출합니다.
이떄, dkms.conf에 ${kernelver} 환경변수는, linux-image-generic.deb에서 값을 세팅해준다. (새로운 커널 버전으로)
결론적으로, /etc/kernel/postinst.d/는 커널 설치 후 필요한 작업을 수행하도록 다양한 서비스나 드라이버가 "등록"하는 시스템 전체 디렉토리입니다. 각 커널 이미지 패키지는 이 공통 디렉토리에 있는 훅을 실행하는 트리거 역할을 할 뿐입니다.