예제: 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 시스템으로 모듈을 빌드해야 합니다.

Posted by cyj4369
,