예제: hello.c 모듈
1) hello.c C 소스 코드를 만들자.(Makefile로 컴파일 하기 위해서는 디렉토리의 경로에 한글이나 공백이 없어야 한다.)
$ mkdir demo; cd demo
$ vi hello.c
2) 다음의 라인을 추가하자.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int __init hello_start(void)
{
printk(KERN_INFO "Loading hello module...\n");
printk(KERN_INFO "Hello world\n");
return 0;
}
static void __exit hello_end(void)
{
printk(KERN_INFO "Goodbye Mr.\n");
}
module_init(hello_start);
module_exit(hello_end);
3) 파일을 저장하고, 새로운 Makefile을 다음과 같이 만들자.(hello.c와 Makefile은 같은 디렉토리에 있어야 한다.)
$ vi Makefile
다음 라인들을 추가하자.
obj-m = hello.o
KVERSION = $(shell uname -r)
all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
부분은 탭으로 띄워야 한다
4) 저장하고 파일을 닫자.
5) hello.c모듈을 컴파일하자.
$ make
6) 루트 계정으로 전환하고 모듈을 로드하자.
$ sudo insmod hello.ko
7) 로드된 모듈을 확인하자.
$ lsmod | less
8) /var/log/message 파일에서 메세지를 확인하자.
9) 모듈을 언로드하자.
$ rmmod hello
10) 리눅스 시스템이 부팅할때 모듈을 로드할 수 있도록, /etc/modules 파일을 수정하자.
이파일은 부팅시 로드할 커널 모듈의 이름을 가지고 있다. 먼저 해당 모듈을 /lib/modules/$(uname -r)/kernel/drivers 에 복사하고, 다음의 단계들을 밝아 나가자.
(a) hello모듈의 디렉토리를 만들자
$ mkdir -p /lib/modules/$(uname -r)/kernel/drivers/hello
(b) 모듈을 복사하자.
$ cp hello.ko /lib/modules/$(uname -r)/kernel/drivers/hello/
(c) /etc/modules파일을 편집하자.
$ vi /etc/modules
(d) 다음 라인을 추가하자.
hello
(e) 변경된 사항을 살펴보기 위해서 재부팅하자. 그리고 lsmod나 dmesg 를 사용해서 로드된 모듈을 확인하자.
$ cat /proc/modules
OR
$ lsmod | less
-c: 커널 모듈은 독립적으로 실행 가능한 파일이 아니며, insmod를 사용하여 실행 시간 중에 커널에 링크되는 오브젝트 파일 이다. 결론적으로 모듈은 -c옵션을 주고 컴파일 해야 한다.
-O2: 커널은 인라인 함수를 주로 사용하기 때문에 모듈은 이 옵션 플래그를 사용해야 한다. 이 옵션을 사용하지 않은 경우 어떤 어셈블러 매크로는 함수 호출 시 정상적으로 작동하지 않을 것이다. insmod는 커널에서 원하는 함수를 찾지 못하고 결국 모듈의 적재는 실패할 것이다.
-W -Wall: 프로그램에서의 실수는 당신의 시스템을 다운 시킬 수도 있다. 컴파일러 경고 기능은 항상 켜둬라, 이것은 모듈 컴파일 뿐 아니라 당신의 모든 컴파일 행위에 적용된다.
-isystem /lib/modules/uname -r/build/include: 컴파일 대상이 되는 커널의 헤더를 사용해야만 한다. 기본적인 /usr/include/linux를 사용하는 것은 작동하지 않을 것이다.
-DKERNEL:이 심볼을 정의 하는 것은 헤더 파일에 이 코드가 유저 프로세스로 동작하지 않고 커널 모드에서 작동한다는 사실을 알린다.
-DMODULE: 이 심볼은 헤더 파일에 커널 모듈을 위한 올바른 정의를 하게 한다.
2.6 커널에서는 linux/init.h 헤더파일이 추가되었습니다. 그리고 init_module()과 cleanup_module() 이라는함수 이름 규약을 더이상 따르지 않아도 됩니다. 초기화 함수와 종료 함수는 자신이 원하는 이름으로 작성하면 되고, module_init()과 module_exit()매크로에서 초기화 함수와 종료 함수의 이름만 지정해주면 됩니다. 물론 2.4 커널의 init_module(), cleanup_module()을 사용해도 되지만, 현재 커널 해커들은 이들 함수를 전혀 사용하고 있지 않습니다. 2.4.20 이후 버전의 커널에서는 위와 같은 2.6 형식의 코드를 사용하고, gcc를 사용해서 모듈로 빌드할 수 있습니다. 2.4.20 이후 버전과 2.6 커널의 모듈은 동일한 코드를 사용할 수 있으며, 빌드 과정만 다릅니다.
2.6 커널부터는 커널 빌드에 대해서 kbuild 시스템을 사용합니다. 따라서 모듈을 빌드하기 위해서 gcc를 사용할 수 없고, Makefile을 정의하고, kbuild 시스템으로 모듈을 빌드해야 합니다.
'Embedded Lab > linux, x86' 카테고리의 다른 글
[Makefile의 미리 정의된 옵션과 타겟] (0) | 2012.10.18 |
---|---|
[안드로이드용 Linux Kernel Source Code 받기] (0) | 2012.10.17 |
[error가 있는지 확인 출력] (0) | 2012.10.15 |
[디스크 공간 할당 방법] (0) | 2012.10.14 |
[Memory Management : Translating Logical Address to Linear Address 1] (0) | 2012.10.08 |