티스토리 뷰

커널이란?
  운영체제(OS, Operating System)의 핵심 부분으로 프로세스, 파일, 네트워크, 장치 등을 관리하는 사용자에게 편리한 인터페이스를 제공해주는 시스템 소프트웨어이다.

  • Monolithic 커널 : 시스템에 관련된 모든 기능을 커널에 때려박은 형태이다. 모든 기능이 커널에서 동작하기 때문에 기능도 많고 Ring 레벨을 변경할 필요가 없기 때문에 빠르지만 기능을 추가하려면 커널을 수정해서 재컴파일해야 한다는 단점 존재
    (Linux는 Monolithic 커널이며, 단점을 해결하기 위해 실시간으로 모듈을 추가할 수 있는 기능을 제공[insmod 명령어])
  • Micro 커널 : 시스템의 주요 핵심 기능만을 커널에 넣고 그 이외는 프로세스로 돌리는 형태이다. 핵심기능은 커널이 처리해주기 때문에 기능 추가를 원할 때 프로세스만 추가하면 커널을 재컴파일해야 하는 일은 없다. 다만, 핵심기능만 커널에서 사용하기 때문에 Ring 레벨의 변화가 자주 있어 좀 느리다.
  • Hybrid 커널 : 커널의 본래 역할이 아니더라도 어느정도 커널에 기능을 집어넣은 Mirco 커널이다. 어느정도 기능을 추가하여 기존의 Micro 커널의 단점을 조금은 해결

Kernel Archives : https://www.kernel.org/



모듈이란?

  커널에서 작업해야 하는 기능이 있는데 이를 추가하기 위해서는 커널을 수정해서 재컴파일해야 한다. 하지만 이는 너무 번거로우므로 리눅스와 같은 운영체제에서는 모듈이라는 기능을 제공하여 특정 커널의 기능을 사용하고자 할 때 실시간(동적)으로 추가할 수 있게 하고 있다.

  예를 들어, USB 드라이버를 생각해보자. USB를 연결하면, 장치가 추가되었기 때문에 이를 처리하기 위해 커널은 처리를 하게 된다. 하지만 커널이 벤더사마다의 USB 드라이버를 설치해두고 있을리가 없으니 USB 드라이버를 통해 커널에 특정 기능을 추가하여 처리할 수 있도록 한다. 만약 특정 기능을 추가하지 못 한다면 USB를 꽂기 위해 USB 드라이버의 기능을 직접 커널에 추가해서 재컴파일해야하는 번거로움이 생길 것이다...



모듈 추가 명령어

1
2
3
4
5
6
$ insmod module.ko    # insert
$ rmmod module.ko    # remove
 
or
 
$ modprobe module
cs

  insmod 명령어는 모듈의 기본 경로를 몰라서 추가해줘야 하고, mobprobe는 모듈의 기본 경로를 알기 때문에 이름만 추가해도 된다. 모듈이 다른 모듈에 의존성을 가지는 경우, 의존하고 있는 모듈을 로드하지 않으면 쓸 수가 없다. 그래서 modprobe는 의존성에 대한 정보를 추정할 수 있어 모듈명만 입력해도 되지만, insmod는 그렇지 않기 때문에 의존성있는 모듈을 직접 추가해야 한다.



모듈 프로그래밍 소스 예제

  커널모듈은 로드될 때 호출되는 함수(entry function)와 제거될 때 호출되는 함수(exit_function)를 반드시 갖추어야 한다.(일종의 생성자, 소멸자 같은...) insmod 명령어를 사용하면 entry function가 호출되어 커널에 작성된 코드나 handler를 등록하거나 대체하는 식으로 커널을 설정하고, rmmod 명령어를 사용하면 exit_function가 호출되어 로드될 때 수행한 기능을 되돌려 커널에서 모듈을 분리한다.


예제 1

1
2
3
4
5
6
7
8
9
10
11
12
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
 
int init_module(void) {
    printk(KERN_INFO "Example 1\n");
 
    return 0;    // not 0 is failed. -> init_module failed.
}
 
void cleanup_module(void) {
    printk(KERN_INFO "Exit Example 1\n");
}
cs

옛날에 많이 사용되던 커널모듈의 생성자 소멸자같은 함수

init_module() : 모듈이 로드될 때 호출됨(entry_funtion), 반환 값이 0이 아니면 모듈을 로드하는데 실패한 것으로 봄

cleanup_module() : 모듈이 제거될 때 호출됨(exit(function)


printk() 함수 : 커널 메시지를 출력하는 함수, 일반적으로 출력되는게 아니라 디버깅과 같은 목적을 지녔으며 로그를 통해 커널 메시지 확인 가능

Makefile

1
2
3
4
5
6
7
8
9
10
obj-m := hello.o
 
PWD := $(shell pwd)
KDIR := /lib/modules/$(shell uname -r)/build
 
default:
    $(MAKE) -C $(KDIR) M=$(PWD) modules
 
clean:
    $(MAKE) -C $(KDIR) M=$(PWD) clean
cs

7번째 줄과 10번째 줄 Tab 간격에 주의하자....


예제 1 동작화면



예제 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <linux/init.h> /* Needed for the macros */
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
 
static int __init hello_init(void) {
    printk(KERN_INFO "Example 2\n");
 
    return 0;    // not 0 is failed. -> init_module failed.
}
 
static void __exit hello_exit(void) {
    printk(KERN_INFO "Exit Example 2\n");
}
 
module_init(hello_init);
module_exit(hello_exit);
cs

  방금 전의 코드는 init_module()과 cleanup_module()이란 함수로 이름이 정해져 있었다. 하지만 예제 2의 경우,  개발자가 직접 모듈의 init와 exit 함수 명을 지정할 수 있다. 그래서 init 헤더 파일을 가져와 module_init와 module_exit 매크로를 사용하고, 매크로의 위에 정의된 함수를 init와 exit로 사용하도록 한다. 


Makefile은 obj-m의 값만 변경하였다.


예제 2 동작화면



예제 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <linux/init.h> /* Needed for the macros */
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
 
static int __init hello_init(void) {
    printk(KERN_INFO "Example 3\n");
 
    return 0;    // not 0 is failed. -> init_module failed.
}
 
static void __exit hello_exit(void) {
    printk(KERN_INFO "Exit Example 3\n");
}
 
module_init(hello_init);
module_exit(hello_exit);
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tribal <tribal@trillion.org>");
MODULE_DESCRIPTION("Test");
cs

  특별한건 아니고 그냥 기존의 소스코드에 GPL(General Public License)라는 것을 등록해서 이 모듈을 누가 만들었는지 명시하였다. 


예제 3 GPL 명시 확인(modinfo 명령어를 쓰면 한 번에 다 볼 수 있음)



모듈 만들 때 중요한 점

  • 잘 정의된 prefix 사용(커널의 prefix는 소문자로 정의되어 있음)
  • 모든 변수를 static으로 선언


참고 

The_Linux_Kernel_Module_Programming_Guide_v2.6_by_YoonMin_Nam.pdf


http://guswnsla1223.tistory.com/82

http://egloos.zum.com/studyfoss/v/4951809






'System > Linux' 카테고리의 다른 글

Linux Device Driver 정리 (2)  (0) 2017.06.01
Linux Device Driver 정리 (1)  (0) 2017.05.28
ptmalloc2 Exploit 기법 정리  (0) 2017.04.26
Pwnable을 위한 Tools 정리  (4) 2017.04.14
Heap 영역 정리  (7) 2017.04.09
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30