Kernel Module

리눅스

목록 보기
3/8

Linux Kernel Module 이란?

Linux에서 Kernel Module필요할 때 커널에 동적으로 로드(load)하거나 언로드(unload)할 수 있는 코드 조각
즉, 커널 전체를 다시 빌드하거나 시스템을 재부팅하지 않고도 커널의 기능을 확장할 수 있는 메커니즘


Loadable Kernel Module (LKM)

Linux kernel에 runtime 중에 코드를 추가하거나 제거할 수 있게 해주는 구조

  • module 없이 kernel 기능 추가:

    • kernel source tree 수정
    • kernel 전체 recompile
  • module 사용:

    • kernel 실행 중에 기능 추가/제거 가능
    • 이때 추가되는 코드 단위를 Loadable Kernel Module이라고 부른다

Kernel Module은 주로 다음 용도로 사용된다:

  • device driver
  • file system
  • network protocol
  • debugging / monitoring 기능

컴파일된 Kernel Module은 보통 .ko (kernel object) 확장자를 가지며,
/lib/modules/ 디렉토리에 위치한다.


Kernel Space vs User Space 개념

Linux 시스템은 크게 다음과 같이 나뉜다:

  • User Space

    • user-level program
    • shell, application
    • GNU C Library (glibc)
  • Kernel Space

    • Linux Kernel
    • device driver
    • kernel module
    • hardware와 직접 통신

User Space의 프로그램은 system call interface를 통해서만 Kernel Space에 접근할 수 있다.
Kernel Module은 Kernel Space에서 실행되므로 아주 강력하지만 매우 위험하다.


Loadable Kernel Module의 장점 요약

Without Kernel Module

  • kernel code 변경
  • kernel 전체 compile
  • system reboot 필요
  • compile time 증가

With Kernel Module

  • module만 compile
  • runtime 중 load/unload 가능
  • reboot 불필요
  • compile time 최소화

주요 Kernel Module 명령어

1️⃣ lsmod

현재 kernel에 로드된 module 목록을 출력한다

$ lsmod
Module           Size    Used by
xor             24576   1 btrfs
zstd_compress   163840  1 btrfs
  • Size: module이 차지하는 memory
  • Used by: 해당 module을 사용하는 다른 module 개수

2️⃣ insmod

Kernel Module을 kernel에 삽입(load)한다

insmod my_module.ko
  • .ko 파일을 kernel에 직접 로드
  • runtime 중 kernel 기능 확장 가능

3️⃣ rmmod

Kernel Module을 kernel에서 제거(unload)한다

rmmod my_module

주의 사항:

  • 다른 module에서 사용 중이면 제거 불가
  • 의존성(dependency)이 있는 경우 순서 중요

4️⃣ modinfo

Kernel Module의 상세 정보를 출력한다

modinfo my_module.ko
  • author
  • license
  • description
  • kernel version 등 확인 가능

Kernel Module 빌드 방법

Kernel Module 소스는 kernel source tree 바깥(out-of-tree)에 있어도 된다

기본 빌드 흐름

  1. module source code 작성
  2. Makefile 작성
  3. make
  4. .ko 파일 생성

Kernel Module Makefile 예제

obj-m := hello_module.o

KERNEL_DIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
	$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules

clean:
	$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean

Makefile 핵심 설명

  • -C $(KERNEL_DIR)

    • kernel source directory로 이동해서 build
  • M=$(PWD)

    • 현재 디렉토리를 external module source로 전달
  • obj-m

    • build할 module object 지정

여러 module을 동시에 컴파일할 수도 있다:

obj-m := module1.o module2.o module3.o

간단한 Kernel Module 코드 예제

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

int __init hello_module_init(void)
{
    printk("Hello Module!\n");
    return 0;
}

void __exit hello_module_cleanup(void)
{
    printk("Bye Module!\n");
}

module_init(hello_module_init);
module_exit(hello_module_cleanup);

MODULE_LICENSE("GPL");

Kernel Module의 Initialization과 Exit

Kernel module은 일반적인 user-level program과 달리
명확한 시작 지점(init)과 종료 지점(exit)을 반드시 가져야 한다

Linux kernel은 module이 언제 로드되고, 언제 언로드되는지를 알아야 하므로
각각에 대응되는 함수를 명시적으로 등록해야 한다


module_init()

module_init(hello_module_init);

module_init()module initialization entry point를 지정하는 매크로다.

의미를 정리하면 다음과 같다.

  • Kernel module이 insmod를 통해 kernel에 insert(load) 될 때
  • module_init()에 등록된 함수가 자동으로 실행된다
  • 위 코드에서는 hello_module_init() 함수가 module의 시작 함수가 된다

즉,

sudo insmod hello_module.ko

를 실행하면,
kernel 내부에서 hello_module_init()이 호출된다.

이 함수 안에서는 보통 다음 작업을 수행한다.

  • resource allocation
  • device register
  • kernel log 출력 (printk)
  • 초기화 작업

module_exit()

module_exit(hello_module_cleanup);

module_exit()module exit entry point를 지정한다.

  • Kernel module이 rmmodremove(unload) 될 때
  • module_exit()에 등록된 함수가 자동으로 실행된다
  • 위 코드에서는 hello_module_cleanup() 함수가 종료 함수 역할을 한다

즉,

sudo rmmod hello_module

를 실행하면,
kernel은 module을 제거하기 전에 hello_module_cleanup()을 먼저 호출한다.

이 함수에서는 보통 다음 작업을 수행한다.

  • resource deallocation
  • device unregister
  • memory free
  • cleanup 작업

Kernel Module은 최소 두 개의 함수가 필요하다

Kernel module은 반드시 다음 두 가지를 포함해야 한다.

  1. Initialization function
  2. Exit function

이유는 kernel이:

  • module이 언제 시작되는지
  • module이 언제 종료되는지

를 명확히 알아야 하기 때문이다.

따라서 init 또는 exit 함수가 없으면
정상적인 kernel module로 동작할 수 없다.


Kernel Module 실행 (Launching a Kernel Module)

왜 root 권한이 필요한가?

Kernel module은 kernel space에서 실행되는 코드

  • user space 프로그램과 달리
  • kernel 전체에 직접적인 영향을 줄 수 있기 때문에
  • 보안 및 안정성 문제로 인해 root privilege가 필요하다

그래서 모든 module 관련 명령어는 sudo가 필요하다


Module Load: insmod

sudo insmod hello_module.ko

이 명령을 실행하면 다음 순서로 동작한다

  1. kernel에 module이 load됨
  2. module_init()에 등록된 함수 실행
  3. 즉, hello_module_init()이 호출됨
  4. module initialization 완료

Module Unload: rmmod

sudo rmmod hello_module

이때의 동작 순서는 다음과 같다

  1. kernel이 module 제거 요청을 받음
  2. module_exit()에 등록된 함수 실행
  3. 즉, hello_module_cleanup()이 호출됨
  4. cleanup 완료 후 module이 완전히 unload됨

Kernel Version 의존성

Kernel module은 특정 kernel version에 맞춰 컴파일된다

uname -r

로 확인한 kernel version을 기준으로 build되며,
다른 version의 kernel에서는 해당 .ko 파일을 로드할 수 없다

즉,

  • kernel version이 다르면
  • module을 다시 compile해야 한다

정리

Kernel module의 lifecycle은 매우 단순하다

insmod → init function 실행
rmmod  → exit function 실행
  • module_init() : module 시작 지점
  • module_exit() : module 종료 지점
  • root 권한 필요
  • kernel version 종속

0개의 댓글