트리 외부 커널 모듈과 같은 트리 내부 커널 모듈을 빌드하는 방법은 무엇입니까?

트리 외부 커널 모듈과 같은 트리 내부 커널 모듈을 빌드하는 방법은 무엇입니까?

나는 사용하고 싶다Oracle Linux UEK7 커널하지만 UEK7DRBD 비활성화, 우리는 그것에 크게 의존합니다.

하지만, 그.src.rpm 사용 가능따라서 이론적으로는 kernel-uek-devel 패키지를 사용하여 원래 .src.rpm 커널 트리에서 트리 외부 모듈로 drbd.ko모듈을 빌드하는 것이 가능합니다 ./lib/modules/$(uname -r)/build

.config한 가지 방법은 전체 RPM을 조정하는 것이지만 rpmbuild -bbOracle의 원래 커널을 계속 부팅하고오직drbd.ko 동일한 버전의 커널에 깔끔하게 로드되도록 모듈을 빌드하세요 .

기본적으로 우리는 마치 트리 외부 커널 모듈인 것처럼 트리 내부 커널 모듈을 구축하려고 합니다. (우리가 원하는 .ko의 커널 버전은 우리가 사용하는 커널 버전과 정확히 동일합니다.)

질문:

  • .src.rpm 제공 커널용으로 게시자가 원래 빌드하지 않은 특정 커널 모듈을 빌드하는 방법은 무엇입니까?

답변1

이것이 제가 UEK6에서 한 일입니다.

빌드 종속성을 설치합니다.

yum group install Development\ Tools -y
yum install kernel-uek-devel kernel-rpm-macros kernel-abi-whitelists -y

Linbit에서 DRBD 소스 tar를 다운로드하고 rpm을 만듭니다.

DRBD_VER="9.1.11"
curl -LO https://pkg.linbit.com//downloads/drbd/9/drbd-${DRBD_VER}.tar.gz
tar xf drbd-${DRBD_VER}.tar.gz
(cd ./drbd-${DRBD_VER} && make kmp-rpm)

귀하의 개정판은 여기에 있습니다: /root/rpmbuild/RPMS/x86_64

자신만의 커널 모듈을 구축할 때의 유일한 문제점은 커널을 업그레이드할 때마다(사소한 업그레이드라도) 모듈을 다시 빌드해야 할 수도 있다는 것입니다.

답변2

커널 UEK R7에서도 거의 동일하게 작동하지만 gcc-toolset-11-annobin-plugin-gcc를 설치하고 scl 활성화 gcc-toolset-11 "make kmp-rpm"으로 빌드해야 합니다.

답변3

이 작업을 원활하게 수행하려면 많은 문제 해결이 필요했습니다. 먼저 다른 답변의 이 링크 지침을 첫 번째 단계로 따르십시오.

그래도 작동하지 않으면 커널 소스 트리에서 실행해야 하는 다음 필수 구성 요소를 실행해야 합니다.

  • zcat /boot/symvers-5.15.0-7.86.6.1.el9uek.x86_64.gz > Module.symvers
  • cp /boot/System.map-5.15.0-7.86.6.1.el9uek.x86_64 System.map
  • cp Module.symvers vmlinux.symvers
  • ./scripts/extract-vmlinux /boot/vmlinuz-5.15.0-7.86.6.1.el9uek.x86_64 > vmlinux

dmesg다음으로, 다음과 같은 오류가 발생하는 경우 :

module: x86/modules: Skipping invalid relocation target, existing value is nonzero for type 1, loc 00000000fbd7a560, val ffffffffc0b33cf0

.config...그런 다음 배포판에서 제공하는 구성 파일과 파일을 비교하는 방법에 세심한 주의를 기울여야 합니다 .

내 경우에는 내 배포판에 포함되지 않은 버전을 빌드 drbd.ko하고 동일한 소스 트리에서 빌드하고 싶습니다. 먼저 distro에서 제공하는 구성을 다음과 같이 distro에서 제공하는 Linux 소스 트리(부팅한 것과 동일한 버전)에 복사했습니다.

cd /usr/src/linux
cp /boot/config-$(uname -r) .config

그런 다음 를 실행하고 make menuconfigDRBD를 활성화한 다음 종료하고 새 구성을 에 저장합니다 .config. 일부 구성 옵션은 Linux 소스 트리 검색에 따라 켜지거나 꺼질 수 있습니다. 생성된 구성 파일을 다음과 같이 배포판에서 제공되는 구성 파일과 비교합니다.

diff -uw /boot/config-$(uname -r) .config

내 구성과 배포판에서 제공하는 구성 간의 관련 차이점을 다음과 같이 단계별로 살펴보겠습니다.

-# Linux/x86_64 5.15.0-7.86.6.1.el9uek.x86_64 Kernel Configuration
+# Linux/x86 5.15.0 Kernel Configuration

여기에는 두 가지 주요 차이점이 있습니다. 가장 먼저 눈에 띄는 차이점은 버전이 잘못되어 EXTRAVERSION=-7.86.6.1.el9uek.x86_64명령줄을 거쳐야 한다는 것입니다 make. 두 번째 차이점은 약간 덜 명확합니다. 첫 번째 광산은 이지만 x86_64두 번째 줄은 x86스키마 유형을 로 전달해야 하기 때문에 입니다 ARCH=x86_64. 그래서 내 make 명령은 다음과 같습니다.

make EXTRAVERSION=-7.86.6.1.el9uek.x86_64 ARCH=x86_64 menuconfig

이제 저장하고 다시 비교하면 버전 라인이 동일한 것을 알 수 있습니다.

내 예에서는 동일한 컴파일러를 사용하고 있지만 컴파일러 버전이 변경되지 않았는지 확인하세요. 그렇다면 배포판에서 사용하는 것과 정확히 동일한 컴파일러를 가져와야 합니다. 예를 들어:

CONFIG_CC_VERSION_TEXT="gcc (GCC) 11.3.1 20220421 (Red Hat 11.3.1-2.1.0.1)"

구성에서 볼 수 있는 다음 차이점은 CTF가 누락되었다는 것입니다.

-CONFIG_HAVE_CTF_TOOLCHAIN=y
...
-CONFIG_CTF=y

오라클에서 제공하는 UEK 커널이기 때문에 dtrace활성화되어 있습니다. dtrace 도구를 다운로드하고 설치함으로써 빌드 체인은 CTF를 감지하고 구성에서 두 가지 다른 CTF 차이점 문제를 해결했습니다.

특정 패키지를 설치하여 해결할 수 있는 몇 가지 구성 차이점이 있으므로 여기에는 다음과 같이 나열하겠습니다.

dnf install dwarves

  • -CONFIG_PAHOLE_HAS_SPLIT_BTF=y:

dnf install dtrace-devel

  • -CONFIG_DEBUG_INFO_BTF_MODULES=y
  • -CONFIG_PAHOLE_HAS_SPLIT_BTF=y
  • -CONFIG_DEBUG_INFO_BTF_MODULES=y
  • -CONFIG_MODULE_ALLOW_BTF_MISMATCH=y
  • -CONFIG_CTF=y

패키지 도 설치했지만 binutils-x86_64-linux-gnu.x86_64위의 문제가 해결되었는지 확실하지 않습니다. 나는 그것이 내 테스트의 일부였기 때문에 언급했습니다. 꼭 필요한 것은 아닐지 모르지만 아직은 모르겠습니다.

DRBD를 빌드하는 명령줄은 이제 다음과 같습니다.

make \
  EXTRAVERSION=-7.86.6.1.el9uek.x86_64 \
  ARCH=x86_64 \
  drivers/block/drbd/drbd.ko

그러나 dmesg여전히 다음 기호 오류가 발생합니다.

drbd: Unknown symbol lc_seq_printf_stats (err -2)
drbd: Unknown symbol lc_get_cumulative (err -2)
drbd: Unknown symbol lc_del (err -2)
drbd: Unknown symbol lc_committed (err -2)
drbd: Unknown symbol lc_get (err -2)
drbd: Unknown symbol lc_try_get (err -2)
drbd: Unknown symbol lc_element_by_index (err -2)
drbd: Unknown symbol lc_create (err -2)
drbd: Unknown symbol lc_try_lock (err -2)
drbd: Unknown symbol lc_destroy (err -2)
drbd: Unknown symbol lc_reset (err -2)
drbd: Unknown symbol lc_is_used (err -2)
drbd: Unknown symbol lc_seq_dump_details (err -2)
drbd: Unknown symbol lc_put (err -2)
drbd: Unknown symbol lc_find (err -2)

diff위 프로세스에서 제가 간과한 것은 .configDRBD가 의존하는 새로운 모듈입니다.

+CONFIG_LRU_CACHE=m

이것을 발견했을 때 누락된 기호를 찾기 위해 몇 가지 작업을 수행했고 커널 모듈 lib/lru_cache.ko도 빌드해야 한다는 것을 발견했습니다. 다음은 DRBD 모듈을 성공적으로 빌드하여 배포판에서 실행 중인 커널로 로드되는 최종 커널 빌드 명령줄입니다.

make \
  EXTRAVERSION=-7.86.6.1.el9uek.x86_64 \
  ARCH=x86_64 \
  lib/lru_cache.ko \
  drivers/block/drbd/drbd.ko

마지막으로 두 모듈을 모두 삽입할 수 있었고 제대로 작동했습니다.

insmod lib/lru_cache.ko
insmod drivers/block/drbd/drbd.ko

이제 이를 /lib/modules디렉터리에 복사하고 실행하면 depmod정상적으로 사용할 수 있습니다.

cp lib/lru_cache.ko drivers/block/drbd/drbd.ko /lib/modules/$(uname -r)/extra/
depmod -a
modprobe drbd
dmesg | tail

마지막으로 다음과 같은 오류가 발생하는 경우:

Skipping BTF generation for drivers/md/raid456.ko due to unavailability of vmlinux

그런 다음 다음과 같이 배포판 vmlinux바이너리를 커널 소스 트리로 추출해야 합니다.

./scripts/extract-vmlinux /boot/vmlinuz-5.15.0-7.86.6.1.el9uek.x86_64 > vmlinux

작동하면 다음과 같이 등록된 블록 장치가 표시됩니다.

drbd: initialized. Version: 8.4.11 (api:1/proto:86-101)
drbd: srcversion: 98E710E58B3041F3046305B 
drbd: registered as block device major 147

관련 정보