임베디드시스템설계강의자료 7 Device Driver (2014 년도 1 학기 ) 김영진 아주대학교전자공학과
디바이스드라이버 (Device Driver) Driver is literally a subject which drive a object. 응용프로그램에서하드웨어장치를이용해서데이터를직접읽고쓰거나제어해야하는경우에디바이스드라이버를이용 하드웨어를제어하는프로그램과애플리케이션에서디바이스를제어하기위한자료구조와함수의집합 응용프로그램이 H/W 를제어할수있도록인터페이스제공 일반적으로위쪽으로는파일시스템과인터페이스를가지며, 아래쪽으로는실제디바이스하드웨어와인터페이스를갖는다. - 2 - Youg-Ji Kim
Liux Device Driver 특성 커널코드 디바이스드라이버는커널의한부분이므로, 커널의다른코드와마찬가지로잘못되면시스템에치명적인피해를줄수있다 커널인터페이스 디바이스드라이버는리눅스커널이나자신이속한서브시스템에표준인터페이스를제공해야한다. 커널메커니즘과서비스 디바이스드라이버는메모리할당, 인터럽트전달, wait queue 같은표준커널서비스를사용할수있다. Loadable 대부분의리눅스디바이스드라이버는커널모듈로서, 필요할때로드하고더이상필요하지않을때언로드할수있다. 설정가능 (Cofigurable) 리눅스디바이스드라이버를커널에포함하여컴파일할수있다. 어떤장치를넣을것인지는커널을 compile 할때설정할수있다 - 3 - Youg-Ji Kim
디바이스드라이버구조 리눅스시스템구조상의디바이스드라이버 Applicatio area Applicatio System Call Iterface VFS Kerel area Buffer Cache Network Subsystem Char Device Driver Block D/D Network D/D Device Iterface Hardware Hardware - 4 - Youg-Ji Kim
디바이스파일 리눅스의디바이스드라이버 RTOS 와달리가상파일시스템 (VFS) 에의해일반파일시스템과공통적인인터페이스제공 디바이스관리를파일을관리하는방법과동일한방법으로관리 응용프로그램에서는일반파일을처리하는경우와동일한시스템콜을호출하여디바이스제어 디바이스파일또는디바이스노드 (ode) 루트파일시스템의 dev 폴더 (/dev) 에있다. 디바이스를표준파일시스템으로관리할수있는인터페이스제공 디바이스정보 디바이스이름 문자디바이스또는블록디바이스구분정보 드라이버를선택하기위한주번호와부번호 접근권한정보 - 5 - Youg-Ji Kim
디바이스파일정보 (Major Number) crw------- 1 root root 4, 64, Oct 01 1970 ttys0 crw------- 1 root root 4, 65, Oct 01 1970 ttys0 (Mior Number) - 6 - Youg-Ji Kim
디바이스노드생성 사용자가직접 mkod 명령사용 형식 : mkod [ 디바이스이름 ] [ 장치유형 ] [ 주번호 ] [ 부번호 ] 사용예 : mkod /dev/test c 125 0 디바이스파일시스템에의한자동생성 - 7 - Youg-Ji Kim
디바이스정보를가지는파일들 /proc/devices 현재 System에장착되어있는 Device들의정보 시스템부팅후에 TARGET에서확인이가능하다. [4412_liux]/Documetatio/devices.txt 현재 Liux System 에서정의되어있는 Device 들의 Major, Mior Number 들에대한정보 [4412_liux]/iclude/liux/major.h Major Number 를 defie 한 header - 8 - Youg-Ji Kim
디바이스드라이버의종류 Character devices Character 디바이스는 File 과같이사용되고, 디바이스드라이버를만드는것은디바이스를파일과같이사용할수있도록하는것 Character 디바이스는 /dev/ttys0 와같이 file system ode 액세스 콘솔, parallel 포트등이 Character 디바이스의예가될수있다 Block devices Block 디바이스는 Character 디바이스와유사하지만, 액세스되는데이터의단위가수 kilo-byte 의블록단위로이루어진다. Block 디바이스도 file system ode 로액세스된다. DISK 가 Block 디바이스의예가될수있다. Network iterface 네트워크로연결된다른호스트와데이터를교환 어플리케이션에서커널영역의드라이버를액세스하는방법은 Character 디바이스나 Block 디바이스와달리 file system ode 를사용하지않는다. - 9 - Youg-Ji Kim
Character Device 드라이버 디바이스 ode Character 디바이스는파일시스템의 /dev 디렉토리에있는디바이스이름또는 ode 를가지고액세스된다. Character 디바이스파일은첫번째칼럼이 c 로표시된다. Character device driver 구현을위한 file operatios register_chrdev/ uregister_chrdev Character 디바이스등록 / 해제 ope 하드웨어초기화 close/release 다바이스를사용되지않도록한다. read 와 write ioctl 커널영역과사용자 (user) 영역간의 character 단위데이타를교환하기위한 file operatio 함수 User 영역에서커널영역으로미리정의된 commad 를가지고제어할수있도록하는 file operatio 함수 - 10 - Youg-Ji Kim
File Operatio Character 디바이스는 user 영역의어플리케이션과 file operatio 을통하여통신이이루어진다. iclude/liux/fs.h 에선언되어있다. struct file_operatios { struct module *ower; loff_t (*llseek) (struct file *, loff_t, it); ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, cost char *, size_t, loff_t *); it (*readdir) (struct file *, void *, filldir_t); usiged it (*poll) (struct file *, struct poll_table_struct *); it (*ioctl) (struct iode *, struct file *, usiged it, usiged log); it (*mmap) (struct file *, struct vm_area_struct *); it (*ope) (struct iode *, struct file *); it (*flush) (struct file *); it (*release) (struct iode *, struct file *); it (*fsyc) (struct file *, struct detry *, it datasyc); ; - 11 - Youg-Ji Kim
Character 디바이스드라이버등록 Character 디바이스드라이버등록 커널의초기화시기에 character device driver 를 file operatio 과함께등록하여야사용이가능하다. it register_chrdev( usiged it major, cost char * ame, struct file_operatios *fops) Character 디바이스드라이버등록해제 it uregister_chrdev(usiged it major, cost char * ame) - 12 - Youg-Ji Kim
문자디바이스드라이버골격 내용소스구성설명 헤더정보선언 함수선언및구현 파일동작구조체선언 등록및해제함수 모듈동작지정 #iclude <liux/iit.h> #iclude <liux/kerel.h> #iclude <liux/module.h> static ssize_t device_read( ) { static ssize_t device_write( ) { static it device_ioctl( ) { static it device_ope( ) { static it device_release( ) { static struct file_operatios device_fops = { read : device_read, write : device_write, ioctl : device_ioctl, ope : device_ope, release : device_release void iit device_iit (void) { register_chrdev( ) void _exit device_exit(void) { uregister_chrdev( ) module_iit(device_iit) module_exit(device_exit) 디바이스드라이버동작에필요한헤더정보를선언한다. 파일동작에의해서문자디바이스를제어하는데필요한함수를구현한다. 함수의이름은일반적으로개발하는디바이스의이름과파일동작이름을사용하여만든다. 디바이스를제어하기위해구현된파일동작함수를파일동작구조체에선언한다. 이구조체는디바이스를등록할때사용된다. 문자디바이스드라이버등록및해제함수 모듈을적재또는제거할때사용되는함수를지정한다 - 13 - Youg-Ji Kim
문자디바이스드라이버함수구현 함수이름파일동작주요기능 [ 디바이스이름 ]_iit [ 디바이스이름 ]_exit [ 디바이스이름 ]_ope ope [ 디바이스이름 ]_release release [ 디바이스이름 ]_read read [ 디바이스이름 ]_write write [ 디바이스이름 ]_ioctl ioctl 함수 register_chrdev( ) 함수를사용하여문자디바이스드라이버를등록한다. 함수 uregister_chrdev( ) 함수를사용하여문자디바이스드라이버사용을해제한다. 디바이스를사용할수있도록하드웨어를초기화하고필요에따라인터럽트를등록하여디바이스가동작할수있도록한다. 더이상디바이스가동작하지않도록하드웨어를중지시키고인터럽트의사용을해제한다. 사용자 (user) 의읽기요청에따라커널영역의데이터를문자단위로전달한다 ([ 그림 5-19] 참조 ). 전달되는데이터는대부분입출력장치에서입력된데이터이다. 사용자 (user) 의쓰기요청에따라사용자영역의데이터를문자단위로가져온다. 사용자영역의데이터는대부분입출력장치에기록된다. 사용자 (user) 영역에서문자디바이스를미리정해진명령에따라다양한방식으로제어할수있는기능을제공한다. - 14 - Youg-Ji Kim
문자디바이스드라이버구현예 1 #iclude <liux/iit.h> #iclude <liux/kerel.h> #iclude <liux/module.h> -- 이하생략 -- static ssize_t device_read (struct file *file, char *buf, size_t cout, loff_t *ppos) { -- 이하생략 -- static ssize_t device_write (struct file *file, char *buf, size_t cout, loff_t *ppos) { -- 이하생략 -- static it device_ope (struct iode *iode, struct file *file) { -- 이하생략 -- static it device_release (struct iode *iode, struct file *file) { -- 이하생략 -- static struct file_operatios device_fops = { ; read: device_read, write: device_write, ope: device_ope, release: device_release, - 15 - Youg-Ji Kim
문자디바이스드라이버구현예 2 static void iit device_iit(void) { register_chrdev(121, device", &device_fops); /* 등록 */ -- 이하생략 -- static void exit device_exit (void) { uregister_chrdev(121, "device"); /* 등록해지 */ -- 이하생략 -- module_iit(device_iit); module_exit(device_exit) - 16 - Youg-Ji Kim
Character 디바이스드라이버초기화 Character 디바이스드라이버는커널초기화시기에 do_iitcall() 에의해서초기화되거나모듈의적재에의해서초기화된다. 개발자는 module_iit 과 iit call 매크로를사용한다 it iit dtk2410_iit(void) { it i; pritk( Registerig Character Device Driver for Traiig\ ); if (register_chrdev(major_nr, test", &dtk2410_fops)) { pritk( Traiig Driver: uable to get major %d\", MAJOR_NR); retur ; retur(0); void exit dtk2410_exit(void) { pritk( Uregister Traiig Driver\"); uregister_chrdev(major_nr, test"); module_iit(dtk2410_iit); module_exit(dtk2410_exit); - 17 - Youg-Ji Kim
문자디바이스어플리케이션 파일액세스방법에의해서처리된다. 프로그래밍절차 Node 정보와함께디바이스 ope Read, write 또는 device 제어디바이스 close character 디바이스를위한 API ope() 시스템콜 사용하려는디바이스에해당하는 iode 할당 ioctl() 시스템콜 User 영역에서디바이스제어 read() 시스템콜 커널영역에서데이터를읽어온다. write() 시스템콜 커널영역으로 user 영역의데이터를보낸다. close 시스템콜 디바이스사용을중지시킨다. ope ( ) ioctl ( ) read ( ) or write ( ) close ( ) - 18 - Youg-Ji Kim
문자디바이스를위한시스템콜 Ope the device it ope (char * fileame, it flags) Read from kerel space it read (it fd, void *buf, size_t bytes) Write to kerel space it write (it fd, void *buf, size_t bytes) Defie Access Mode O_RDONLY O_WRONLY O_RDWR O_CREATE. I/O cotrol it ioctl (it fd, it cmd, argumets) Close the device it close (it fd) - 19 - Youg-Ji Kim
디바이스드라이버 ope 어플리케이션에서디바이스파일이름과함께 ope( ) 함수가호출되면디바이스파일정보에따라서아이노드 (iode) 와 filp 변수정보로분배되어파일동작구조체에따라디바이스드라이버의 device_ope() 함수를호출 fd = ope( /dev/device, O_RDWR); it device_ope ( struct iode *iode, struct file *filp ) { retur 0; - 20 - Youg-Ji Kim
디바이스드라이버 close 디바이스를종료하기위해서는 close( ) 함수사용 애플리케이션에서 close 가호출되면디바이스드라이버의 device_release( ) 함수실행 - 21 - Youg-Ji Kim
디바이스제어를위한 IOCTL IOCTL 시스템콜 디바이스드라이버제어에있어서다양한용도로사용디바이스제어뿐만아니라데이터입출력도구현가능 - 22 - Youg-Ji Kim
디바이스드라이버에서데이터읽기 애플리케이션에서 read( ) 호출 디바이스드라이버에서상용자영역의버퍼에요구하는크기만큼복사 copy_to_user( ) 라는함수가사용 읽기동작실행된후에는크기정보를리턴 le = read ( fd, buf, size ); ssize_t device_read ( struct file *filp, char *buf, size_t cout, loff_t *ppos) copy_to_user - 23 - Youg-Ji Kim
디바이스드라이버에데이터쓰기 어플리케이션에서 write( ) 호출 사용자영역에준비되어있는버퍼에있는데이터를디바이스드라이버내의버퍼에요청한크기만큼기록 copy_from_user( ) 함수사용 기록후에는기록한개수를리턴 - 24 - Youg-Ji Kim
문자디바이스애플리케이션예 it mai(it argc, char *argv[]) { it fd, ret, le; char buf[8]; usiged log args; /* 디바이스장치파일을이용하여오픈, 이때접근권한도설정 */ fd = ope ("/dev/device", O_RDWR); if (fd == -1) { /* 에러처리 */ /* IOCTL 을사용한문자장치제어, 명령 (CMD) 와인자를사용 */ ret = ioctl(fd, CMD,&args); if (ret<0) { /* 에러처리 */ /* 커널영역의데이터를읽는다 (read) */ le = read(fd, buf, 8);.. /* 커널영역의데이터를읽는다 (read) */ le = write(fd, buf, 8);.. /* 문자디바이스사용종료 */ ret = close(fd); retur ret; - 25 - Youg-Ji Kim
Skeleto 디바이스드라이버실습 skeleto.c #iclude <liux/module.h> #iclude <liux/fs.h> #iclude <liux/kerel.h> #iclude <liux/iit.h> #iclude <liux/major.h> MODULE_LICENSE("GPL"); it result; it skeleto_ope(struct iode *iode, struct file *filp) { pritk("device Ope!!\"); retur 0; it skeleto_release(struct iode *iode, struct file *filp) { pritk("device Release!!\"); retur 0; it skeleto_read(struct file *filp, cost char *buf, size_t cout, loff_t *f_pos){ pritk("device Read!!\"); retur 0; it skeleto_ioctl(struct file *filp, usiged it cmd, usiged log arg) { pritk("device Ioctl!!\"); retur 0; 디바이스드라이버코드 - 26 - Youg-Ji Kim
Skeleto 디바이스드라이버실습 skeleto.c it skeleto_write(struct file *filp, usiged it *buf, size_t cout, loff_t *f_pos) { pritk("device Write!!\"); retur 0; 디바이스드라이버코드 struct file_operatios skeleto_fops = {.ope = skeleto_ope,.release= skeleto_release,.read = skeleto_read,.ulocked_ioctl = skeleto_ioctl,.write = skeleto_write, ; static it skeleto_iit(void) { pritk("skeleto module iit!!\"); result = register_chrdev(248, "skeleto", &skeleto_fops); pritk( retur value=%d\", result); retur 0; If major == 0 this fuctios will dyamically allocate a major ad retur its umber. If major > 0 this fuctio will attempt to reserve a device with the give major umber ad will retur zero o success. Returs a -ve erro o failure. static void skeleto_exit(void) { pritk("skeleto module exit!!\"); module_iit(skeleto_iit); module_exit(skeleto_exit); - 27 - Youg-Ji Kim
Skeleto 디바이스드라이버실습 Makefile Makefile for 디바이스드라이버코드 CC KDIR := /usr/local/codesourcery/sourcery_g++_lite/bi/arm-oe-eabi-gcc := /4412_Liux/kerel_4412 obj-m := skeleto.o build : make -C $(KDIR) SUBDIRS=$(PWD) modules clea : rm -rf *.o *.ko *.mod.c *.order *.symvers - 28 - Youg-Ji Kim
Skeleto 디바이스드라이버실습 userapp.c 디바이스드라이버응용프로그램 #iclude <stdio.h> #iclude <fctl.h> #iclude <uistd.h> #iclude <stdlib.h> #iclude <strig.h> it mai() { it fd; fd = ope("/dev/skeleto2", O_RDWR); pritf("device Driver Test Applicatio\"); read(fd, 0, 0); ioctl(fd, NULL, 0); close(fd); retur 0; - 29 - Youg-Ji Kim
Skeleto 디바이스드라이버실습 DeviceDriver module Build Buildig 디바이스드라이버코드 (make 사용 ) # make - 30 - Youg-Ji Kim
Skeleto 디바이스드라이버실습 Applicatio Build Buildig 디바이스드라이버응용프로그램 # arm-liux-gueabihf-gcc userapp.c o userapp - 31 - Youg-Ji Kim
Skeleto 디바이스드라이버실습 ismod Loadig 디바이스드라이버및응용수행 # mkod /dev/skeleto2 c 248 0 # ismod skeleto.ko #./userapp # lsmod # dmesg - 32 - Youg-Ji Kim