리눅스 디바이스 드라이버 프로그래밍(2) - 모듈 프로그래밍
글 작성자: _rian
커널 모듈 (Kernel Module)
- 시스템 부팅 후에 동적으로 loading 할 수 있는 커널 구성 요소를 말한다.
- 커널을 다시 컴파일하거나 시스템 재부팅 할 필요 없이 커널의 일부분을 교체하는 것이 가능하다
- 디바이스 드라이버, 파일 시스템, 네트워크 프로토콜 등이 모듈로 제공된다.
일반 응용 프로그램과 뭐가 다른거지?
커널 모듈은 일반 응용 프로그램과 달리 main 함수가 없다.
대신에 커널에 로딩 및 제거될 때 불러지는 함수가 존재하는데, 이는 아래와 같다.
- Loading 시 : module_init() 로 지정된 함수 호출
- Unloading 시 : module_exit() 로 지정된 함수 호출
리눅스 디바이스 드라이버의 특성
1) 커널 코드
디바이스 드라이버는 커널의 한 부분이므로, 커널의 다른 코드와 마찬가지로 잘못되면 시스템에 치명적인 피해를 줄 수 있다.
2) 커널 인터페이스
디바이스 드라이버는 리눅스 커널이나 자신이 속한 서브시스템에 표준 인터페이스를 제공해야 한다.
3) 커널 매커니즘과 서비스
디바이스 드라이버는 메모리 할당, 인터럽트 전달, wait queue와 같은 표준 커널 서비스를 사용할 수 있다.
4) Loadable
대부분의 리눅스 드라이버는 커널 모듈로서, 필요할 때 Load 하고 더이상 필요하지 않을 때 unload 할 수 있다.
5) 설정 가능(Configurable)
리눅스 디바이스 드라이버를 커널에 포함하여 컴파일 할 수 있다. 어떤 장치를 넣을 것인지는 커널을 컴파일 할 때 설정할 수 있다.
간단한 커널 모듈 작성 - hello
커널에 모듈이 로딩될 때 "Hello, linux kernel module"를 출력하는 프로그램을 만들어보자!
1. hello.c
//hello.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("BUTTER SHOWER");
MODULE_DESCRIPTION("module programming - hello module");
static int __init module_begin(void){
printk("Hello, linux kernel module. \n");
return 0;
}
static void __exit module_end(void){
printk("Good Bye!\n");
}
module_init(module_begin);
module_exit(module_end);
- 필요한 include 파일들 include 시켜주기
- moudle lincense 지정
- lincense 종류 : GPL, GPL v2, Dual BSD/GPL, Proprietary 등
- 커널 2.6부터 반드시 지정해야 함 - module_init 함수 작성 및 등록 : module_init(init_func);
- module_exit 함수 작성 및 등록 : module_exit(exit_func);
2. 커널 모듈 프로그램을 위한 Makefile
obj-m += hello.o
all:
make -C /lib/modules/${shell uname -r)/build M=$(PWD) moduels
clean:
make -C /lib/moudles/$(shell uname -r)/build M=$(PWD) clean
Makefile 이라는 이름으로 위의 코드를 붙여 만들어준 후, make 명령어를 하면 아래와 같이 실행된다.
컴파일 과정
- hello.o 파일 먼저 생성
- modpost를 C 소스파일에 적용해 .ko에서 요구되는 추가 정보를 부착하여 hello.mod.c를 생성한 후 컴파일 -> hello.mod.o 생성
- 두개의 .o 파일을 링크하여 .ko (kernel object) 파일을 생성
3. 모듈 적재(loading) 그리고 제거(unloading)
생성된 모듈(hello.ko) 을 로딩
insmod hello.ko
커널에 적재된 모듈 목록 보기
lsmod
모듈 제거
rmmod hello //(.ko가 붙지 않음)
hello 모듈 동작 확인
모듈 적재와 제거 시에 메시지들이 출력되는지를 확인
#dmesg 또는
#tail -f /var/log/kern.log (-f 옵션 : 계속적인 변화 출력)
디바이스 드라이버 작성 방법
1. 디바이스 드라이버 함수 작성
- struct file_operations 정의
- open, release, read, write, ioctl 함수 구현
- init, exit 함수 구현
2. 커널에 디바이스 드라이버 등록 - init 함수에서 수행
int res;
res = register_chardev(); //char driver
res = register_blkdev(); //block driver
res = register_netdev(); //network driver
(사실 register_xxxdev() 함수 파라미터에 필요한 값들이 있지만 일단 생략.. 추후 포스팅 예시를 보면 알 것이다)
3. 컴파일/로딩
#make ... Makefile 작성 후 실행
#insmod ... 생성된 .ko 파일 load
4. 디바이스 파일 생성
#mknod [디바이스파일이름] [드라이버타입] [주번호] [부번호]
(예시)
#mknod /dev/LED c 239 0
필요하면 속성을 변경해주면 된다.
#chmod ug+w /dev/LED
5. 디바이스 파일에 입출력하는 응용프로그램 작성 및 테스트
디바이스 파일에 입출력하는 응용 프로그램을 작성하고, 테스트한다.
커널 영역을 침범하는 파일이기 때문에 작성에 유의해야 한다.
디바이스 드라이버 골격
디바이스 드라이버의 골격은 아래와 같다.
Header Files |
|
Function Prototypes & Definitions |
|
File Operation |
|
모듈 설치시 초기화 수행 모듈 제거시 반환 작업 수행 |
|
'Computer Engineering > 임베디드 시스템' 카테고리의 다른 글
리눅스 디바이스 드라이버 프로그래밍(4) - ioctl 함수, blocked 입력 (0) | 2019.06.13 |
---|---|
리눅스 디바이스 드라이버 프로그래밍(3) - 7segment led 예제 fpga에 적용시켜보기 (0) | 2019.06.13 |
리눅스 디바이스 드라이버 프로그래밍(1) - 디바이스 드라이버 개요, 디바이스 드라이버 종류 (0) | 2019.06.12 |
임베디드 리눅스 커널 프로그래밍(3) - 시스템 호출 함수 구현 (0) | 2019.06.12 |
임베디드 리눅스 커널 프로그래밍(2) - 커널 데이터타입, 커널 인터페이스 함수 (0) | 2019.06.11 |
댓글
이 글 공유하기
다른 글
-
리눅스 디바이스 드라이버 프로그래밍(4) - ioctl 함수, blocked 입력
리눅스 디바이스 드라이버 프로그래밍(4) - ioctl 함수, blocked 입력
2019.06.13 -
리눅스 디바이스 드라이버 프로그래밍(3) - 7segment led 예제 fpga에 적용시켜보기
리눅스 디바이스 드라이버 프로그래밍(3) - 7segment led 예제 fpga에 적용시켜보기
2019.06.13 -
리눅스 디바이스 드라이버 프로그래밍(1) - 디바이스 드라이버 개요, 디바이스 드라이버 종류
리눅스 디바이스 드라이버 프로그래밍(1) - 디바이스 드라이버 개요, 디바이스 드라이버 종류
2019.06.12 -
임베디드 리눅스 커널 프로그래밍(3) - 시스템 호출 함수 구현
임베디드 리눅스 커널 프로그래밍(3) - 시스템 호출 함수 구현
2019.06.12