Download presentation
Presentation is loading. Please wait.
1
문자 디바이스 드라이버 임베디드 시스템
2
목차 커널 설정 커널 모듈 실습 : 커널 모듈 작성 리눅스 디바이스 드라이버
실습 : Dummy 디바이스 드라이버 작성 및 사용 문자 디바이스 드라이버
3
kernel configuration 기본 kernel 부팅을 위한 설정들
MTD file system을 mount하기 위한 설정들
4
system type
5
Serial drivers Device drivers -> Character devices -> Serial drivers
6
Boot options
7
MTD Device drivers -> Memory Technology Devices (MTD) ->
8
MTD Device drivers -> Memory Technology Devices (MTD) ->
Ram/Rom/Flash chip drivers
9
MTD Device drivers -> Memory Technology Devices (MTD) ->
Mapping drivers for chip access
10
File systems File systems -> Miscellaneous filesystems ->
11
커널 모듈 시스템 부팅 후에 동적으로 loading 할 수 있는 커널 구성요소
커널을 다시 컴파일 하거나 시스템 리부팅 할 필요 없이 커널의 일부분을 교체하는 것이 가능 디바이스 드라이버, 파일 시스템, 네트워크 프로토콜 등이 모듈로 제공됨 컴파일한 커널 버전 정보가 들어가야 하고, 현재 실행되고 있는 커널 버전과 일치해야 함 <linux/module.h>에 정의되어 있음 모듈 정보는 전체 모듈에서 하나만 존재해야 함 일반 응용 프로그램과의 차이점 main() 함수가 없음 커널에 로딩 및 제거 될 때 불러지는 함수가 존재 Loading 시 - int init_module(void) 함수 호출 Unloading 시 - void cleanup_module() 함수 호출 문자 디바이스 드라이버
12
실습 : 커널 모듈 작성 Hello World 프로그램 모듈이 로딩될 때 모듈이 제거될 때 Hello world 출력
Goodbye world 출력 /* hello.c */ #include <linux/module.h> /* 모든 모듈에 필요 */ #include <linux/kernel.h> /* printk() 등에 필요 */ int hello_init(void) { // 모듈이 로딩될 때 호출 printk (“Hello world\n”); return 0; } void hello_exit(void) { // 제거 될 때 호출 printk (“Goodbye world”); module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE(“GPL”); 문자 디바이스 드라이버
13
실습 : 커널 모듈 컴파일 arm-linux-gcc 컴파일러를 이용 오른쪽과 같이 Makefile 작성
#Makefile obj-m := hello.o KDIR :=$(커널 소스가 설치된 절대 경로) PWD :=$(shell pwd) all: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: rm -rf *.ko rm -rf *.mod.* rm -rf .*.cmd rm -rf *.o 문자 디바이스 드라이버
14
실습 : 커널 모듈 적재 & 제거 생성된 모듈을 로딩 커널에 적재된 모듈 목록 보기 모듈 제거
rx hello.ko 시리얼 통신(x모뎀)을 통해 타겟으로 컴파일한 ko 파일 전송 insmod hello.ko 커널에 적재된 모듈 목록 보기 lsmod 모듈 제거 rmmod hello 모듈 적재와 제거 시에 원래 의도했던 메시지들이 출력되는 지 확인 문자 디바이스 드라이버
15
리눅스 디바이스 드라이버 실제 장치 부분을 추상화 시켜 사용자 프로그램이 정형화된 인터페이스를 통해 디바이스를 접근할 수 있도록 해주는 프로그램 디바이스 관리에 필요한 정형화된 인터페이스 구현에 요구되는 함수와 자료구조의 집합체 표준적으로 동일 서비스 제공을 목적으로 커널의 일부분으로 내장 하드웨어 독립적인 프로그램을 작성을 가능하게 함 파일 연산을 통해 장치를 제어 문자 디바이스 드라이버
16
리눅스 디바이스 드라이버의 종류 문자 디바이스 드라이버 블록 디바이스 드라이버 네트워크 디바이스 드라이버
자료의 순차성을 지닌 장치 입출력연산 한번으로 임의의 데이터 전송 예) 키보드, 시리얼 포트 등 블록 디바이스 드라이버 블록 단위로 데이터 입출력 파일시스템에 마운트 되어 관리되는 장치 입출력연산 한번으로 고정된 크기의 데이터 전송 예) 하드 디스크, CD롬, 플로피 디스크 등 네트워크 디바이스 드라이버 대응하는 장치파일이 없음 응용프로그램과의 통신은 표준 파일 시스템관련 콜 대신 socket(), bind() 등의 시스템 콜 사용 문자 디바이스 드라이버
17
리눅스 디바이스 드라이버의 종류(2) Application System Call Interface VFS
Network Subsystem Buffer Cache Network D/D Block D/D Character D/D Device Interface Hardware Application area Kernel area 문자 디바이스 드라이버
18
디바이스 장치 파일 리눅스에서 장치는 파일로 인식됨 ls –l /dev 명령을 이용하여 확인 가능 디바이스 종류 주번호 부번호
문자 디바이스 드라이버
19
디바이스 장치 파일(2) 주 번호(Major Number) 부 번호(Minor Number)
커널에서 디바이스 드라이버를 구분/연결하는데 사용 같은 Device의 종류를 지칭, 1Byte (0~255사이의 값) 부 번호(Minor Number) 디바이스 드라이버 내에서 장치를 구분하기 위해 사용 각 Device의 부가적인 정보를 나타냄, 2Byte (부번호) 하나의 디바이스 드라이버가 여러 개의 디바이스 제어 가능 주번호 부번호 문자 디바이스 드라이버
20
문자 디바이스 드라이버 기본 골격 헤더 파일 파일 연산 함수 정의 파일 연산 구조체
#include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> int device_open( … ) { … } int device_release( … ) { … } ssize_t device_write( … ) { … } ssize_t device_read( … ) { … } static struct file_operations device_fops = { … ssize_t (*read) (…); ssize_t (*write) (…); int (*open) (…); int (*release) (…); }; int init_module(void) { … } void cleanup_module(void) { … } module_init(hello_init); module_exit(hello_exit); 헤더 파일 파일 연산 함수 정의 파일 연산 구조체 문자 디바이스 드라이버
21
디바이스 드라이버 작성 방법 디바이스 드라이버 등록
드라이버를 커널에 등록하고, 파일 연산을 정의하는 등의 초기화 작업 수행이 필요 insmod를 이용하여 모듈이 커널에 로딩될 시 init함수에서 초기화 수행 문자 드라이버 등록 함수 커널에 지정되어 있는 chrdevs 구조에 새로운 문자 드라이버 등록 major number : 주번호, 0을 주면 사용하지 않는 값을 반환 name : 디바이스 이름으로 /proc/devices에 나타남 fops: 디바이스와 연관된 파일 연산 구조체 포인터 음수가 반환되면 오류가 발생했음을 나타냄 int register_chrdev( unsigned int major, const * name, struct file_operations * fops); 문자 디바이스 드라이버
22
디바이스 드라이버 작성 방법(2) 디바이스 드라이버 제거 rmmod 명령으로 드라이버가 제거될 때 cleanup 함수에서 호출
디바이스 드라이버 작성 방법(2) 디바이스 드라이버 제거 rmmod 명령으로 드라이버가 제거될 때 cleanup 함수에서 호출 문자 드라이버 제거 함수 int unregister_chrdev( unsigned int major, const * name); 문자 디바이스 드라이버
23
디바이스 드라이버 작성 방법(3) 파일 연산 구조체 정의 디바이스 드라이버를 일반적인 파일과 유사한 인터페이스를 이용하여 관리
각 디바이스는 파일 형태로 존재하고, 커널은 파일 연산을 이용하여 I/O 연산을 수행하도록 인터페이스 구성 디바이스 드라이버를 구현한다는 것은 상당부분 파일연산 구조체에서 요구되는 기능들을 프로그래밍 한다는 것을 의미 struct file_operations dummy_fops = { .owner = THIS_MODULE, .open = dummy_open, .read = dummy_read, .write = dummy_write, .ioctl = dummy_ioctl .release = dummy_release, }; 문자 디바이스 드라이버
24
디바이스 드라이버 작성 방법(4) 파일 연산의 종류 read write ioctl mmap open release
디바이스에서 데이터를 가져오기 위해서 사용 write 디바이스에 데이터를 쓰기 위해서 사용 ioctl 디비아스에 종속적인 명령을 만들기 위해 사용 mmap 디바이스 메모리를 프로세스 메모리에 매핑 open 디바이스를 열 때 수행 release 디바이스를 닫을 때 수행 문자 디바이스 드라이버
25
실습 : Dummy 디바이스 드라이버 작성 헤더 파일 및 매크로 정의 #include <linux/module.h>
#include <linux/kernel.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/fcntl.h> #define DUMMY_NAME “dummy” #define DUMMY_MAJOR_NUMBER 240 문자 디바이스 드라이버
26
실습 : Dummy 디바이스 드라이버 작성(2)
드라이버 등록 static int dummy_init(void) { int ret; printk(“dummy init\n”); ret = register_chrdev(DUMMY_MAJOR_NUMBER, DUMMY_NAME, &dummy_fops); if (res < 0) return ret; return 0; } module_init(dummy_init); 문자 디바이스 드라이버
27
실습 : Dummy 디바이스 드라이버 작성(3)
드라이버 제거 static void dummy_exit(void) { printk(“dummy exit\n”); unregister_chrdev( DUMMY_MAJOR_NUMBER, DUMMY_NAME); } module_exit(dummy_exit); MODULE_LICENSE(“GPL”); 문자 디바이스 드라이버
28
실습 : Dummy 디바이스 드라이버 작성(4)
파일 연산 구조체 정의 struct file_operations dummy_fops = { .owner = THIS_MODULE, .open = dummy_open, .read = dummy_read, .write = dummy_write, .ioctl = dummy_ioctl, .release = dummy_release, }; 문자 디바이스 드라이버
29
실습 : Dummy 디바이스 드라이버 작성(5)
open & release int dummy_open(struct inode *inode, struct file *filep) { int num = MINOR(inode->i_rdev); printk(“dummy dev open -> minor %d\n”, num); return 0; } int dummy_release(struct inode *inode, struct file *filep) printk(“dummy dev close\n”); 문자 디바이스 드라이버
30
실습 : Dummy 디바이스 드라이버 작성(6)
read & write size_t dummy_read(struct file *filep, char *buf, size_t count, loff_t *f_pos) { printk(“dummy dev read -> buf 0x%08x, count 0x%08x\n”, buf, count); return 0x33; } size_t dummy_write(struct file *filep, const char *buf, size_t count, loff_t *f_pos) printk(“dummy dev write -> buf 0x%08x, count 0x%08x\n”, buf, count); return 0x43; 문자 디바이스 드라이버
31
실습 : Dummy 디바이스 드라이버 작성(7)
ioctl int dummy_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { printk(“dummy dev ioctl -> cmd 0x%08x, arg 0x%08x\n”, cmd, arg); return 0x53; } 문자 디바이스 드라이버
32
실습 : Dummy 드라이버를 제어하기 위한 어플리케이션 작성
app.c #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #define DEV_NAME “/dev/dummy_device” int main() { int dev; char buf[128]; int ret; printf(“1> device open\n”); dev = open(DEV_NAME, O_RDWR|O_NDELAY); printf(“dev %d\n”, dev); if (dev >= 0) { printf(“2> read function\n”); ret = read(dev, 0x30, 0x31); printf(“ret = 0x%x08x\n”, ret); printf(“3> write function\n”); ret = write(dev, 0x40, 0x41); printf(“4> ioctl function\n”); ret = ioctl(dev, 0x51, 0x52); printf(“ret = 0x%x08x\n”, printf(“5> device close\n”); ret = close(dev); } return 0; } 문자 디바이스 드라이버
33
실습 : 디바이스 드라이버 적재 및 삭제 디바이스 드라이버 컴파일 디바이스 드라이버 적재 노드 생성 디바이스 드라이버 삭제
커널 모듈 실습과 동일 디바이스 드라이버 적재 insmod dummy.ko 노드 생성 디바이스를 사용하기 위해서는 노드 (파일)을 생성해야 함 노드(파일)를 통해서 입출력 수행 mknod /dev/dummy_device c 240 0 디바이스 드라이버 삭제 rmmod dummy 드라이버의 적재 여부 lsmod 문자 디바이스 드라이버
Similar presentations