본문 바로가기
임베디드 개발/리눅스 디바이스 드라이버

LDD ] 리눅스 커널 모듈 In-tree building

by eteo 2024. 10. 4.

 

 

In-tree 빌드란?

 

In-tree 빌드는 커널 모듈을 리눅스 커널 소스 트리 안에 추가하여 커널 빌드 시스템이 커널과 함께 해당 모듈을 빌드하도록 하는 방법이다. 이 방법을 사용하면 사용자는 menuconfig 명령어를 통해 메뉴 형태로 구성된 커널 설정 화면에서 모듈을 선택하거나 선택해제할 수 있다.

 

 

 

In-tree building 과정 요약

  1. 리눅스 커널 소스 트리 내에 모듈 추가
  2. 로컬 Kconfig 파일 작성
  3. 로컬 Makefile 작성
  4. 상위 레벨 Kconfig 파일에 로컬 Koconfig 파일 추가
  5. 상위 레벨 Makefile에 로컬 Makefile 추가
  6. 커널 소스 루트 디렉토리로 이동해서 make menuconfig를 이용해 설정 (Optional)
  7. 커널 소스 루트 디렉토리로 이동해서 모듈 빌드

 

 

1. 리눅스 커널 소스 트리 내에 모듈 추가

 

리눅스 커널 소스 트리 내에 모듈을 추가할 디렉토리를 생성한 뒤 모듈 소스 파일을 배치한다.

$cd <kernel-source-top>/drivers/char
$mkdir my_c_dev
$cd my_c_dev
$vim hello.c
#include<linux/module.h>

static int __init hello_init(void)
{
    pr_info("Hello world\n");
    return 0;
}

static void __exit hello_exit(void)
{
    pr_info("Goodbye world\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("ME");
MODULE_DESCRIPTION("A simple Hello World kernel module");

 

 

 

 

2. 로컬 Kconfig 파일 작성

 

menuconfig에 모듈을 선택할 수 있는 메뉴 항목을 추가하려면 menu 키워드로 시작하고 endmenu 키워드로 끝나는 메뉴 항목을 Kconfig 파일에 작성해야 한다. 위에서 생성한 디렉토리 내에 로컬 Kconfig 파일을 작성한다.

$vim Kconfig
menu "my custom modules"
config CUSTOM_HELLOWORLD
 tristate "hello world module support"
 default n
endmenu

 

  • menu 뒤에 오는 "my custom modules"는 menuconfig에서 환경설정 시 볼 수 있는 메뉴 항목의 이름이다.
  • config 뒤에 오는 CUSTOM_HELLOWORLD는 앞에 CONFIG_가 붙어 커널 구성 파일(.config)에서 식별자로 사용된다.
  • tristate는 이 설정 항목이 세 가지 상태를 가질 수 있음을 나타내고 그 뒤에 오는 문자열을 사용자에게 표시될 설명문이다.
  • 옵션 y(정적), n(비활성), m(동적) 중에서 기본 옵션을 지정하기 위해 default 키워드를 사용한다.

 

 

 

 

 

3. 로컬 Makefile 작성

 

역시 같은 디렉토리 내 로컬 Makefile을 만든다. 그리고 리눅스 커널 빌드 시스템에서 사용하는 obj-<X> 변수에 빌드할 모듈을 추가 정의한다.

$vim Makefile
obj-$(CONFIG_CUSTOM_HELLOWORLD) += hello.o

 

위에서 $(CONFIG_CUSTOM_HELLOWORLD)는 사용자가 menuconfig를 통해 빌드 옵션을 수정했을 때 .config 파일에서 해당 식별자를 통해 실제 선택된 옵션을 찾아 y 또는 n 또는 m으로 대치된다.

그리고 obj-<X> 변수를 통해 리눅스 커널 소스 트리에 존재하는 여러 다른 모듈과 같이 빌드되므로 여기서는 :=가 아닌 += 연산자를 사용한다.

 

 

 

 

 

 

4. 상위 레벨 Kconfig 파일에 로컬 Koconfig 파일 추가

 

상위 디렉토리(<kernel-source-top>/drivers/char/)로 이동해서 상위 레벨의 Kconfig 파일 끝 endmenu 윗 줄에 다음과 같이 추가한다.

$cd ..
$vim Kconfig
source "drivers/char/my_c_dev/Kconfig"

 

 

 

5. 상위 레벨 Makefile에 로컬 Makefile 추가

 

상위 Makefile에서 하위 Makefile을 찾을 수 있도록 끝줄에 다음 문구를 추가한다.

$vim Makefile

 

 

 

6. 커널 소스 루트 디렉토리로 이동해서 make menuconfig를 이용해 설정한다.

 

Device Drivers > Character devices 에서 my custom modules가 추가된 것을 확인할 수 있다.

 

 

 

엔터를 치고 들어가 스페이스를 여러번 치면 빌드 옵션을 바꿀 수 있다.

  • <M> : 동적으로 커널에 로드 및 언로드 될 수 있는 독립적인 개체(.ko 파일)로 빌드 됨
  • < * > : 커널 이미지에 직접 통합됨
  • <   > : 모듈을 빌드하지 않음

<M>으로 설정한 뒤 저장하고 빠져나오면 .config 파일이 생성되는 데 로컬 Kconfig 파일에 지정했던 식별자 앞에 CONFIG_를 붙여 검색하면 설정을 찾아볼 수 있다.

$vim .config
/CONFIG_CUSTOM_HELLOWORLD

 

 

 

이후 아래 명령어로 커널 소스 모듈을 빌드하면 최초 생성했던 디렉토리 안에 .ko 파일이 생성된 것을 확인할 수 있다.

 

$make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules -j4

 

modinfo 명령어로 확인해보면 intree: 에 Y 표시가 되어있다.

 

 

 

참고 :

Fastbit Embedded Brain Academy

https://medium.com/@adityapatnaik27/linux-kernel-module-in-tree-vs-out-of-tree-build-77596fc35891