Step by Step 커널 프로그래밍 강좌②
작성자 정보
- 웹관리자 작성
- 작성일
컨텐츠 정보
- 26,628 조회
- 0 추천
- 목록
본문
Step by Step 커널 프로그래밍 강좌②
모듈구현하기
지난 호에 우리는 리눅스 커널의 관한 기본적인 내용들과 함께 새로운 커널을 컴파일하기
위한 방법을 배웠다. 이번 호에는 지난 호에 이어 우리가 새롭게 컴파일한 커널에 일부가 되
어 동작할 수 있는 모듈 프로그래밍에 관해 알아보기로 한다. 본 강좌는 지난 호에서 새롭게
컴파일한 커널로 부팅하여 동작하고 있다는 가정 하에 진행하기로 한다.
글 _ 김민찬 KLDP 멤버, 전문 프로그래머
연재 순서
① 커널 프로그래밍의 환경 구축
② 모듈 구현하기
③ 커널의 동기화에 관하여
④ 커널의 시간관리 및 지연 함수에 대하여
⑤ 파일시스템과 proc file system 사용하기
⑥ 디버깅 기술에 관하여
1. 커널 모듈이란 ?
모듈이란 동적으로 커널 속으로 로드 또는 언로드 될 수 있는 코드의 묶음을 말한다. 이렇게 해서 얻을 수 있는 장점은 시스템을 재부팅하지 않고도 필요할 때 필요한 기능을 동적으로
커널에 추가할 수 있다는 점이다. 이런 것들의 가장 흔한 예는 장치 드라이버나 파일 시스템들이 될 수 있다. 만일 모듈이 없다면 이런 장치들을 위한 코드나 자주 사용하지 않는 파일 시스템을 위한 코드들을 커널을 빌드할 때 이미 포함한 상태로 컴파일을 해야 하므로 커널의 크기가 점점 커지게 되며 메모리 사용량 또한 증가하게 된다. 더욱 아찔한 것은 미처 생각치 못한 기능을 넣지 못했다면 필요할 때 마다 커널을 다시 빌드해야 한다는 점이다. 여러분은 앞으로 어떤 장치를 새로 사용하게 될지 미리 예측할 수 있는가?
자, 현재 여러분의 시스템에는 어떤 모듈들이 사용되고 있을까? 이를 알아보는 명령어는 다음과 같다.
lsmod
이 명령어는 /proc/modules을 읽어들어 출력하게 된다. 그렇다면 여러분들은 언제 이 모듈들을 로드 했는지 기억이 나는가? 커널 모듈은 kmod라는 데몬에 의해 커널이 필요로 할 때
자동적으로 로드되게 된다. 이 일을 담당하는 kmod라는 데몬이 커널 내에 존재하게 되며 커널이 자신이 갖고 있지 않은 새로운 기능을 필요로 할 때 modprobe라는 어플리케이션을 실
행시켜 필요한 모듈을 로드하게 되는 것이다. modprobe는 필요한 모듈을 찾기 위해서 /etc/modprebe.conf 설정 파일을 먼저 찾게 되며 필요한 모듈을 로드하기 전에 어떤 다른 모듈
을 먼저 로드해야 하는지를 살피기 위하여 /lib/modules/version/modules.dep 파일을 살피게 된다. 이 파일은 다음 명령어를 통해 만들 수 있다.
depmod -a
modprobe는 모듈간의 의존성을파악한 후 마지막으로 insmod라는 어플리케이션을 실행하여 커널에 모듈을 로드하게 된다. 이때 로드되는 모듈들은 /lib/modules/version/ 디
렉토리에서 찾게 된다. 지금까지 본 것처럼 insmod는 마지막에 실행되는 어플리케이션으로써 단지 module을 로드하는 일만 하지만 modprobe는 insmod를 실행시킬 뿐만 아니라 모
듈들의 위치, 상호 의존성 체크까지 다 알아서 해준다. 그러므로 모듈을 로드할 때 insmod를 사용하는 것보다는 modprobe를 사용하는 것이 편리할 때가 많다. 하지만 명령어를 사용할 때 주의해야 할 것이 modprobe는 아래와 같이 확장자를 취하지 않는 다는 점이다. 또한 modprobe를 사용하기위해서는 위에서 설명한 설정 파일들에 적절하게 명시되어 있어야 한다.
insmod /lib/modules/2.6.11/kernel/fs/fat/fat.ko
insmod /lib/modules/2.6.11/kernel/fs/msdos/msdos.ko
modprobe msdos
modprobe, insmod, depmod는 module-init-tools라는 패키지로 각 배포판마다 제공된다.
2. 모듈 작성하기
자, 이제 우리는 새로운 모듈을 작성할 준비가 다 되었다. 지금부터 여느 프로그램을 배울 때와 마찬가지로 이번에도 helloworld 모듈을 작성할 것이다. 가장 기본적인 모듈 프로그램을
통해 각 함수들의 역할과 기능에 대해 알아보도록 한다.
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h>/* Needed for KERN_EMERG */
#include <linux/init.h> /* Needed for the macros */
static int __init hello_init(void)
{
printk(KERN_ EMERG"Hello, world ");
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_EMERG "Goodbye, world ");
}
module_init(hello_init);
module_exit(hello_exit);
커널 모듈들은 적어도 두 가지의 함수는 반드시 가지고 있어야 한다. 그 함수들은 module_init과 module_exit의 매크로로 등록된 함수들이다.
module_init 매크로로 등록된 함수는 insmod 명령을 통해 모듈이 커널에 등록될 때 호출되는 함수이며 반대로, module_exit는 rmmod 명령을 통해 커널에서 언로드될 때 호출되는 함수이다. 각 함수들의 선언에 붙여진 매크로는 다음과 같은 의미를 갖는다.
● __init 매크로는 커널로 하여금 init 함수가 사용된 후 그 함수가 차지했던 메모리 공간을 회수할 수 있도록 하기위한 방법이다. 하지만 이 매크로는 모듈로 만들어진 커널드라이버들에게는 적용되지 않고 built-in 드라이버들에
게만 적용된다.
이렇게 하는 이유는 커널의 입장에서 built-in 드라이버들의 init 함수들은 한번 실행되고 나며 더 이상 사용되지 않을 것이기 때문에 그 코드들이 차지하는 메모리 공간을 회수하여 최대한 많은 메모리를 확보할 수 있기 때문이다.
● __exit 매크로는 커널의 built-in 드라이버들을 만들어 하나의 커널 이미지를 빌드할 때 그 함수들을 커널의 이미지에서 뺄 수 있도록 하기 위한 방법이다.그렇게 하는 이유는 built-in 드라이버들은 커널이 살아있는 동안 메모리에서 언로드되지 않기 때문에 _exit 함수가
전혀 호출되지 않는다. 그러므로 굳이 실행되지 않는 함수를 커널의 이미지에 포함시켜 커널의 사이즈를 크게 만들필요가 없기 때문이다.
마지막으로 printk 함수는 printf와 같이 단순히 console에 출력을 하기 위한 함수와는 다르다. 이 함수는 커널의 여러 정보들을 기록하는 데 사용된다. printk함수는 8개의 우선순위
로 이루어진 매크로들을 사용하여 출력할 수 있으며 각 우선 순위마다 아래의 표와 같은 의미를 가지고 있다. 커널의 많은함수들은 상황에 맞는 우선순위를 사용하여 정보들을 로깅하
고있다.
여러분이 어떤 매크로도 명시하지 않는다면 default priority인 DEFAULT_MESSAGE_LOGLEVEL을 사용하게 될 것이며 이 정보는 kernel/printk.c에 다음과 같이 정의되어 있다.
/* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
우선순위가 console_loglevel 값보다 커야만(즉, 숫자로는 작은 수) 메시지가 터미널을 통해 화면에 출력될 수 있다. console_loglevel 값은 필자의 시스템에는 다음과 같이 정의되어 있다.
#define console_loglevel (console_printk[0])
int console_printk[4] = {
DEFAULT_CONSOLE_LOGLEVEL,
/* console_loglevel */
DEFAULT_MESSAGE_LOGLEVEL,
/* default_message_loglevel */
MINIMUM_CONSOLE_LOGLEVEL,
/* minimum_console_loglevel */
DEFAULT_CONSOLE_LOGLEVEL,
/* default_console_loglevel */
};
#define DEFAULT_CONSOLE_LOGLEVEL 7 /
* anything MORE serious than KERN_DEBUG */
우리는 이 예제에서 제일 높은 우선순위를 갖는 KERN_EMERG를 사용하였다. 왜냐하면 default priority의 메시지는
관련자료
-
이전
-
다음