BOBO's Note

Kernel Module과 Device Driver 본문

Embedded System

Kernel Module과 Device Driver

bobo_hee 2020. 5. 29. 22:18

Kernel Modules 

커널 모듈은 커널 모드로 실행되어야 하는 프로그램이며 확장자는 .ko이다. 부팅 후 필요할 때 동적으로 로드해 커널에 포함시킬 수 있어 커널 이미지 크기를 줄이는 데에 도움을 주고, 부팅 시간을 줄여준다. root 권한을 가진 사용자만 커널 모듈을 로드/언로드할 수 있다.

 

dmesg 커맨드로 시스템 부팅시 출력되는 메세지와 커널에서 출력(예. printk(), pr_info(), pr_alert() 등)하는 로그 메세지를 확인할 수 있다.

 

kernel module과 관련된 커맨드는 다음과 같다.

  • modinfo <module_name>: 해당 커널 모듈에 대한 정보를 출력한다.

  • lsmod: 로드된 커널 모듈 목록을 출력한다.

  • sudo insmod <moodule_path>.ko: 해당 커널 모듈을 로드한다.

  • sudo rmmod <module_name>: 해당 커널 모듈을 삭제/언로드한다.

  • sudo modprobe <module_name>: 해당 커널 모듈의 dependency를 고려해서 자동으로 관련된 커널 모듈까지 함께 로드한다. 관련된 커널 모듈은 /lib/modules/<kernel-version>/ 에서 찾는다.

  • sudo modprobe -r <module_name>: 해당 커널 모듈의 dependency까지 고려해서 더이상 사용하지 않는 모든 커널 모듈들을 삭제/언로드한다.

    • /lib/modules/<kernel-version>/modules.dep 을 참고해 dependency를 파악한다.

Device Driver

디바이스 드라이버는 하드웨어를 제어하는 소프트웨어이다. 대부분의 드라이버가 커널 모듈로 개발되지만, user space에서 실행되는 디바이스 드라이버도 존재한다. 다음과 같을 때 user space로 개발한다.

  • 오직 한 애플리케이션에서만 HW에 접근하기 때문에 커널에서 굳이 multiplexer 기능을 제공할 필요가 없을 때

  • 커널의 하위시스템(예. 네트워크 스택, 파일시스템 등)을 접근할 필요가 없을 때

user space driver의 장점 및 단점

디바이스 드라이버를 user space에서 개발하면 표준 라이브러리를 사용할 수 있어 개발이 용이하고, 꼭 C가 아니더라도 개발할 수 있다. 그리고 오픈소스로 공개할 필요도 없으며 중간에 메모리에서 swap-out 될 수 있다. 때때로 user space로 개발하면 성능이 더 좋을 수 있는데, 그 이유는 커널 모듈로 개발하면 드라이버를 호출할 때마다 커널 모드로 전환되는 오버헤드가 발생하기 때문이다. 또한 드라이버 실행에 문제가 생겼을 때 커널 모듈은 kernel crash가 발생하지만 user space 드라이버는 해당 프로세스만 종료된다는 장점이 있다.

 

그렇지만 user space 드라이버는 용도가 제한적이고 CPU에 의해 스케쥴링되어야 실행되므로 응답 속도가 느리다. 그리고 인터럽트 처리에도 한계가 있다.

 

Kernel Module 예제 코드 분석

#include <linux/init.h>
#include <linux/module.h>
#include <linux.kernel.h>

// Initialization function
static int __init hello_init(void){
	pr_alert("Hello!\n");
    return 0;
}

// Cleanup funcion
static void __exit hello_exit(void){
	pr_alert("Bye!\n");
}

// Macros that designate initialization/cleanup functions
module_init(hello_init);
module_exit(hello_exit);

// Metadata information
MODULE_LICENSE("GPL");
MODULE_DESCRIPTER("Simple kernel module");
MODULE_AUTHOR("Bohee Lee");

__init 매크로는 초기화 과정에서 한번만 호출하는 함수 및 변수에 붙여준다. insmod 또는 modprobe로 해당 커널 모듈을 로드할 때 호출된 후, 이 함수는 메모리 상에서 삭제된다.

 

__exit 매크로는 종료될 때 호출하는 함수 및 변수에 붙여준다. rmmod 또는 modprobe -r로 해당 커널 모듈을 삭제할 때 호출된다. 따라서 커널에 static하게 함께 컴파일되거나 삭제될 일이 없는 모듈의 경우, 해당 함수를 메모리에 올리지 않는다.

 

module_init()module_exit()에 함수 포인터를 넘겨주어 초기화 및 삭제 함수를 지정해준다.

'Embedded System' 카테고리의 다른 글

GPIO  (0) 2020.06.04
Interrupt Handler  (0) 2020.06.03
Android Boot Sequence  (0) 2020.05.26
임베디드 시스템의 Boot Sequence  (0) 2020.05.26
Generic Boot Sequence  (0) 2020.05.25
Comments