-
모듈은 요청 시 커널에 로드 및 언로드할 수 있는 코드 조각이다.
-
시스템을 재부팅할 필요 없이 커널의 기능을 확장한다.
- 예를 들어, 한 가지 유형의 모듈은 커널이 시스템에 연결된 하드웨어에 액세스할 수 있도록 하는 디바이스 드라이버이다.
- 모듈이 없으면 모놀리식 커널을 빌드하고 커널 이미지에 직접 새로운 기능을 추가해야 하고, 새로운 기능을 원할 때마다 커널을 다시 빌드 및 재부팅해야 한다는 단점이 있다.
- 따라서 모듈을 이용하면 커널 컴파일 시간을 단축할 수 있다.
-
로드 가능한 커널 모듈(LKM, Loadable Kernel Module)은 런타임에 Linux 커널에 코드를 추가하거나 제거하는 메커니즘이다.
- 모듈 없이 Linux 커널에 코드를 추가하려는 경우 가장 기본적인 방법은 커널 소스 트리에 일부 소스 코드 또는 파일을 추가하고 커널을 다시 컴파일하는 것이다.
- 모듈을 사용하면 Linux 커널이 실행되는 동안 코드를 추가할 수 있다.
- 이러한 방식으로 추가하는 코드 덩어리를 로드 가능한 커널 모듈이라고 한다.
- 모듈은 커널이 하드웨어와 통신할 수 있도록 하는 디바이스 드라이버에 이상적이다.
- 모듈은
/lib/modules/
디렉터리에서.ko
(kernel object, 커널 개체) 확장자를 가진 파일로 나타낼 수 있다. - 디바이스 드라이버는 모듈 형태로 구성되어 있다.
- 파일 시스템, 메모리 매니지먼트 또한 커널 형태로 구성할 수 있다.
- 모듈은
-
요약: KCM은 모듈별 빌드가 가능하도록 하여 컴파일 시간을 최소화한다.
-
lsmod
- 현재 설치된 사용중인 모듈을 보여준다.
- lsmod 명령은 현재 커널에 설치된 모듈을 나열하는 데 사용할 수 있다.
- 결과는 모듈의 이름, Size 및 usage(Used by) 목록이다.
- "Used by"(usage)는 이 모듈을 사용하는 다른 모듈의 수를 의미한다.
$ lsmod Module Size Used by udp_diag 16384 0 raw_diag 16384 0 unix_diag 16384 0 ...
-
insmod
- 모듈을 삽입하기 위해 사용하는 명령이다.
- insmod(또는 insert module, 모듈 삽입) 명령을 사용하여 커널에 모듈을 삽입할 수 있다.
- 사용자가 런타임에 커널 모듈을 로드하여 커널 기능을 확장할 수 있다.
insmod my_module.ko
-> 커널 개체 파일(.ko)을 커널에 삽입한다.
-
rmmod
- 모듈을 제거할 때 사용하는 명령이다.
- rmmod(또는 remove module, 모듈 제거) 명령은 실행 중인 커널에서 로드 가능한 모듈을 언로드한다.
- 모듈을 삭제하기 위해선 사용 중이 아니어야 하고, 다른 모듈에서 참조하지 않아야 한다.
- 명령줄에서 둘 이상의 모듈 이름이 지정되면 해당 모듈은 지정된 순서대로 제거된다.
- 이것은 스택된 모듈의 언로드를 지원한다.
-
modinfo
-
모듈 정보를 얻으려고 할 때 사용하는 명령이다.
-
Linux 시스템에서 modinfo 명령은 Linux 커널 모듈에 대한 정보를 표시하는 데 사용된다.
-
이 명령은 명령줄에 제공된 Linux 커널 모듈에서 정보를 추출한다.
$ modinfo udp_diag filename: /lib/modules/5.15.0-1019-aws/kernel/net/ipv4/udp_diag.ko alias: net-pf-16-proto-4-type-2-136 alias: net-pf-16-proto-4-type-2-17 license: GPL srcversion: A6913F04E5CF94B0DEC8CAB depends: inet_diag retpoline: Y intree: Y name: udp_diag vermagic: 5.15.0-1019-aws SMP mod_unload modversions sig_id: PKCS#7
-
-
modprobe
-
모듈을 설치/삭제하는 명령어
-
insmod/rmmod 명령어와 다르게
modules.dep
파일을 참조해 의존성 문제를 해결$ modprobe --help Usage: modprobe [options] [-i] [-b] modulename modprobe [options] -a [-i] [-b] modulename [modulename...] modprobe [options] -r [-i] modulename modprobe [options] -r -a [-i] modulename [modulename...] modprobe [options] -c modprobe [options] --dump-modversions filename Management Options: -a, --all Consider every non-argument to be a module name to be inserted or removed (-r) -r, --remove Remove modules instead of inserting --remove-dependencies Also remove modules depending on it
-
-
depmod
-
의존성을 검사하여
modules.dep
파일을 갱신하는 명령어$ depmod --help Usage: depmod -[aA] [options] [forced_version] If no arguments (except options) are given, "depmod -a" is assumed depmod will output a dependency list suitable for the modprobe utility.
-
- 모듈의 소스 코드는 커널 소스 트리 밖에 있을 수 있다.
- 모듈 소스 디렉토리에 메이크파일을 넣는다.
- 컴파일 후 컴파일된 모듈은 확장자가 .ko인 파일이다.
-
$ vi Makefile
```bash #------Makefile------# obj-m := hello_module.o KERNEL_DIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNAL_DIR) SUBDIR=${PWD} modules clean: $(MAKE) -C $(KERNAL_DIR) SUBDIR=${PWD} clean ```
오브젝트 모듈:= hello_module.o
- 컴파일할 모듈의 이름을 넣으면 된다.
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
- 커널 디렉토리
- shell uname : 커널 버전이 나온다.
- 커널 버전에 맞는 빌드 디렉토리를 넣어야 한다.
PWD := $(shell pwd)
- 소스코드가 있는 디렉토리
- Print Working Directory
default : $(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules
- default는 뒤에 아무 옵션을 주지 않았을 때 시행되는 명령어이다.
- 커널 디렉토리와 서브 디렉토리를 넣어준다.
- 모듈 컴파일이니 modules를 붙인다.
clean : $(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) clean
- clean: make clean 썼을 때 시행되는 명령어이다.
#--------- hello_module.c ---------#
#include <linux/kernel.h> //Needed by all modules
#include <linux/module.h> //Needed for KERN_ALERT
#include <linux/init.h> //Needed for the macros
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");
-
.c
파일을 만들어 세 가지 커널 헤더를 include한다. -
insmod
는 해당 모듈을 로드한다. 파일의 module_init 함수를 부른다. -
rmmod
는 해당 모듈을 언로드한다. 파일의 module_exit 함수를 부른다. -
모듈 초기화 및 종료
- module_init(hello_module_init)
- 초기화 진입점
- 모듈 삽입 시 실행할 함수 (hello_module_init)
hello_module_init()
는 모듈을 로드할 때 호출된다.
- module_exit(hello_module_cleanup)
- 출구 진입점
- 모듈 제거 시 실행할 함수(hello_module_cleanup)
hello_module_cleanup()
은 모듈을 언로드할 때 호출된다.
- module_init(hello_module_init)
-
커널 모듈에는 최소한 두 가지 함수가 있어야 한다.
- 모듈이 커널에 insmod될 때 호출되는 "시작"(initialization) 함수(예:
hello_module_init
()) - 모듈이 커널에 rmmod될 때 호출되는 "종료"(cleanup) 함수(예:
hello_module_cleanup
())
- 모듈이 커널에 insmod될 때 호출되는 "시작"(initialization) 함수(예:
-
커널 모듈 시작
- 커널 코드를 실행하기 때문에 루트 권한이 필요하다.
insmod
로 커널 모듈을 로드해야 한다.insmod hello_module.ko
(반드시 .ko를 붙여야 한다.)- 모듈이 로드되고 초기화 함수가 실행된다.
- 모듈은 특정 커널 버전에 대해 컴파일되며 다른 커널에는 로드되지 않는다.
rmmod
로 모듈 제거rmmod hello_module
또는rmmod hello_module.ko
- 언로드 전에 모듈 종료 함수가 호출된다.