리눅스 디바이스 드라이버

39
리리리 리리리리 리리리리 리리 리리 리리 리 리리

description

리눅스 디바이스 드라이버. 실습 환경 설정 및 준비. 커널 컴파일. 디바이스 파일 (1). 디바이스 파일 (2). mknod 명령 디바이스 파일 생성 mknod [ 디바이스 파일명 ] [ 파일 형 ] [ 주 번호 ] [ 부 번호 ] mknod /dev/devfile c 240 1. 디바이스 드라이버 탐색. 실질적인 디바이스 탐색. 저수준 파일 입출력 함수. 모듈 유틸리티. insmod 모듈을 커널에 적재한다 . rmmod 커널에 등록된 모듈을 제거한다 . lsmod - PowerPoint PPT Presentation

Transcript of 리눅스 디바이스 드라이버

Page 1: 리눅스 디바이스 드라이버

리눅스 디바이스 드라이버

실습 환경 설정 및 준비

Page 2: 리눅스 디바이스 드라이버

커널 컴파일 버전 커널 컴파일 과정

커널 2.4 Loadable module support ----- >

[*] Enable loadable module support

[*] Set version information on all module

symbols

[*] Kernel module loader

커널 2.6 Loadable module support ----- >

[*] Enable loadable module support

[*] module unloading

[*] Forced module unloading

[*] Module versioning support (EXPERIMENTAL)

[*] Automatic kernel module loading

Page 3: 리눅스 디바이스 드라이버

디바이스 파일 (1)

Page 4: 리눅스 디바이스 드라이버

디바이스 파일 (2)

• mknod 명령–디바이스 파일 생성

–mknod [ 디바이스 파일명 ] [ 파일 형 ] [ 주 번호 ] [ 부 번호 ]

–mknod /dev/devfile c 240 1

디바이스드라이버 탐색

실질적인디바이스 탐색

Page 5: 리눅스 디바이스 드라이버

저수준 파일 입출력 함수

저수준 파일 입출력 함수 기능

open() 파일이나 장치를 연다

close() 열린 파일을 닫는다

read() 파일에서 데이터를 읽어온다

write() 파일에 데이터를 쓴다

lseek() 파일의 쓰기나 읽기 위치를 변경한다

ioctl() Read(), write() 로 다루지 않는 특수한 제어를 한다

fsync() 파일에 쓴 데이터와 실제 하드웨어의 동기를 맞춘다

Page 6: 리눅스 디바이스 드라이버

모듈 유틸리티

• insmod–모듈을 커널에 적재한다 .

• rmmod–커널에 등록된 모듈을 제거한다 .

• lsmod–커널에 등록된 모듈의 상태를 보여준다 .

Page 7: 리눅스 디바이스 드라이버

모듈 소스 형식 (1)

• 헤더 파일 선언

• 모듈 초기화 함수 , 제거 함수

커널 2.6

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

커널 2.6

module_init(hello_init);module_exit(hello_exit);

Page 8: 리눅스 디바이스 드라이버

모듈 컴파일용 Makefile

obj-m := test.o // 모듈로 생성할 이름 지정

KDIR := /lib/modules/$(shell uname -r)/build // 커널의 소스 위치 지정PWD := $(shell pwd) // 컴파일 대상의 모듈 소스의 위치

default: // 모듈을 컴파일하는 명령 지정 $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modulesclean: // 컴파일 결과로 생성된 파일을 모 rm -rf *.ko // 두 지운다 . rm -rf *.mod.* rm -rf .*.cmd rm -rf *.o

Page 9: 리눅스 디바이스 드라이버

모듈 프로그램 맛보기 (1)

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

static int hello_init(void){ printk("Hello, world \n"); return 0;}

static void hello_exit(void){ printk("Goodbye, world\n");}

module_init(hello_init);module_exit(hello_exit);

MODULE_LICENSE("Dual BSD/GPL");

• test.c

Page 10: 리눅스 디바이스 드라이버

모듈 프로그램 맛보기 (2)

obj-m := test.o

KDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)

default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modulesclean: rm -rf *.ko rm -rf *.mod.* rm -rf .*.cmd rm -rf *.o

• Makefile

Page 11: 리눅스 디바이스 드라이버

동적 메모리 할당 함수

kmalloc()kfree()

할당 속도가 빠르고 사용법이 간단해 디바이스 드라이버에서 가장 많이 사용되는 함수 ( 할당 크기 제한 있음 ).

vmalloc()vfree()

가상공간이 허용하는 한 크기 제한 없이할당 받을 수 있다 . 큰 메모리 공간을할당할 때 주로 사용한다 ( 속도가 느리다 ).

__get_free_pages()__free_pages()

잘 사용되지 않는 함수 .

Page 12: 리눅스 디바이스 드라이버

kmalloc(), kfree()-1

메모리주소 kmalloc( 할당 받을 크기 , 옵션 );kfree( 메모리주소 );

* 할당 가능한 최대 크기는 32 x PAGE_SIZE ( 일반적으로 128KB)

#include <linux/slab.h>

char *buf;

buf = kmalloc(1024, GFP_KERNEL);

if (buf != NULL){ … kfree(buf);}

Page 13: 리눅스 디바이스 드라이버

vmalloc(), vfree()

메모리주소 vmalloc( 할당 받을 크기 );vfree( 메모리주소 );

#include <linux/vmalloc.h>

char *buf;

buf = vmalloc(1024);

if (buf != NULL){ … vfree(buf);}

Page 14: 리눅스 디바이스 드라이버

vmalloc(), vfree() 특징

- 가상 주소 공간에서 할당받기 때문에 해당주소의 영역이 하드디스크에 있을 수도 있어 실패할 수 있다 .

- 커다란 연속된 공간을 할당하기 위해 가상메모리 관리 루틴이 수행되기 때문에 kmalloc() 보다 속도가 매우 느리다 .

- 할당 시 프로세스가 잠들지 못하게 할 수 없기 때문에 인터럽트 서비스 함수 안에서는 사용할 수 없다 .

Page 15: 리눅스 디바이스 드라이버

__get_free_pages(), free_pages()

메모리주소 __get_free_pages( 옵션 , 차수 );free_pages( 메모리주소 );

#include <linux/mm.h> //2.4#include <linux/gfp.h> //2.6#include <asm/page.h> //get_order

char *buf;

buf = __get_free_pages(GFP_KERNEL, order); /* order=0 이면 1 개의 page, order=3 이면 3 개의 page /* MAX_ORDER 은 11, 그러나 5 이하의 값만 사용하는 것이 안전 (32*PAGE_SIZE) */

if (buf != NULL){ … free_pages(buf, order);}

Page 16: 리눅스 디바이스 드라이버
Page 17: 리눅스 디바이스 드라이버
Page 18: 리눅스 디바이스 드라이버
Page 19: 리눅스 디바이스 드라이버
Page 20: 리눅스 디바이스 드라이버
Page 21: 리눅스 디바이스 드라이버
Page 22: 리눅스 디바이스 드라이버
Page 23: 리눅스 디바이스 드라이버
Page 24: 리눅스 디바이스 드라이버

초기화와 종료 처리• module_init 의 초기화 처리

① 디바이스 드라이버의 등록

② 디바이스 드라이버에 내부 구조체의 메모리 할당

③ 여러 프로세스가 하나의 디바이스에 접근하는 경우에 사전처리

④ 주 번호에 종속된 부 번호를 관리하기 위한 사전 처리

⑤ 하드웨어 검출 처리 및 에러 처리

⑥ 하드웨어 초기화

Page 25: 리눅스 디바이스 드라이버

초기화와 종료 처리module_exit 의 종료 처리

초기화 시점에 할당된 메모리 모두 반납( 디바이스 드라이버는 커널의 일부이기 때문에 메모리를 자동 반납하지 않는

다 .)

① 디바이스 드라이버의 해제

② 디바이스 드라이버에 할당된 모든 메모리의 해제

③ 하드웨어 제거에 따른 처리

Page 26: 리눅스 디바이스 드라이버

초기화와 종료 처리• module_exit 처리순서

void xxx_exit(void){

kfree(… // 디바이스 드라이버에 할당된 모든 메모리 해제unregister_chrdev(… // 디바이스 드라이버의 해제xxx_shutdown(… // 하드웨어 제거에 따른 처리

}

Page 27: 리눅스 디바이스 드라이버

초기화와 종료 처리디바이스 드라이버 open( ) 함수 [2]

int fd;int fd;

fd = open( DEVICE_FILENAME, O_RDWR|O_NDELAY); fd = open( DEVICE_FILENAME, O_RDWR|O_NDELAY); // 반드시 주번호 정보가 있는 파일

if( fd < 0 ) { if( fd < 0 ) {

printf (“error number %d\n”, error);printf (“error number %d\n”, error);

exit(1); exit(1);

}}

int fd;int fd;

fd = open( DEVICE_FILENAME, O_RDWR|O_NDELAY); fd = open( DEVICE_FILENAME, O_RDWR|O_NDELAY); // 반드시 주번호 정보가 있는 파일

if( fd < 0 ) { if( fd < 0 ) {

printf (“error number %d\n”, error);printf (“error number %d\n”, error);

exit(1); exit(1);

}}#include<linux/fs.h>#include<linux/fs.h>

struct file_operations call_fops = { struct file_operations call_fops = {

……

.open .open = xxx_open, = xxx_open,

… … }}

#include<linux/fs.h>#include<linux/fs.h>

struct file_operations call_fops = { struct file_operations call_fops = {

……

.open .open = xxx_open, = xxx_open,

… … }}

int xxx_open( struct inode *inode, struct file *filp ) {int xxx_open( struct inode *inode, struct file *filp ) {

int err = 0;int err = 0;//open() 시 처리내용들… .

return err;return err;

}}

int xxx_open( struct inode *inode, struct file *filp ) {int xxx_open( struct inode *inode, struct file *filp ) {

int err = 0;int err = 0;//open() 시 처리내용들… .

return err;return err;

}}

*inode – 열린 디바이스 파일에 대한 정보

*filp – 디바이스 드라이버 처리관련 정보

*inode – 열린 디바이스 파일에 대한 정보

*filp – 디바이스 드라이버 처리관련 정보

ENODEV : 하드웨어가 존재하지 않는다 .ENOMEM : 커널 메모리가 부족하다 .EBUSY : 디바이스가 이미 사용중 이다 .

ENODEV : 하드웨어가 존재하지 않는다 .ENOMEM : 커널 메모리가 부족하다 .EBUSY : 디바이스가 이미 사용중 이다 .

Page 28: 리눅스 디바이스 드라이버

초기화와 종료 처리디바이스 드라이버 release( ) 함수 [1]

release( ) 함수 호출 시 종료 처리프로세스별 할당 메모리 해제모듈 사용 횟수 감소 ( 커널 2.4)

커널 2.6 에서는 사용횟수 관리를 커널에서 한다 .

Page 29: 리눅스 디바이스 드라이버

초기화와 종료 처리디바이스 드라이버 release( ) 함수 [2]

if( fd ) close( fd );if( fd ) close( fd );if( fd ) close( fd );if( fd ) close( fd );

#include<linux/fs.h>#include<linux/fs.h>

struct file_operations call_fops = { struct file_operations call_fops = {

……

.release .release = xxx_release, = xxx_release,

… … }}

#include<linux/fs.h>#include<linux/fs.h>

struct file_operations call_fops = { struct file_operations call_fops = {

……

.release .release = xxx_release, = xxx_release,

… … }}

int xxx_release( struct inode *inode, struct file *filp ) int xxx_release( struct inode *inode, struct file *filp )

{{//close( ) 시 처리내용들… .

return 0;return 0;

}}

int xxx_release( struct inode *inode, struct file *filp ) int xxx_release( struct inode *inode, struct file *filp )

{{//close( ) 시 처리내용들… .

return 0;return 0;

}}

Page 30: 리눅스 디바이스 드라이버

문자 디바이스 드라이버 동작 -3

디바이스 드라이버하드웨어인터럽트

응용 프로그램

open();write();

insmod

rmmod

xxx_init();

struct file_operations{ open : xxx_open write : xxx_write . . .}

xxx_exit();

xxx_interupt();

xxx_open();

xxx_write();

Page 31: 리눅스 디바이스 드라이버

커널 2.6 의 파일 오퍼레이션 구조체

struct file_operations{ struct module *owner; int (*open)(struct inode *, struct file *); . . .}

* 디바이스 드라이버의 file_operations 에서 정의되지 않았거나 NULL 로 채워진 필드는 커널에 의해서 default 처리를 한다 .

Page 32: 리눅스 디바이스 드라이버

#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/types.h>#inlcude <linux/fcntl.h>int xxx_open (struct inode *inode, struct file *filp){}int xxx_release(struct inode *inode, struct file *filp){}struct file_operations xxx_fops ={ .owner = THIS_MODULE,

.open = xxx_open,

.release = xxx_release,};int xxx_init(void){ register_chrdev(240, “char_dev”, &xxx_fops);}void xxx_exit(void) { unreister_chrdev(240, “char_dev”);}module_init(xxx_init);module_exit(xxx_exit);

Page 33: 리눅스 디바이스 드라이버

mknod /dev/calldev c 240 32

Page 34: 리눅스 디바이스 드라이버
Page 35: 리눅스 디바이스 드라이버

make

Page 36: 리눅스 디바이스 드라이버

insmod call_dev.ko

Page 37: 리눅스 디바이스 드라이버

app(call_app) 컴파일

Page 38: 리눅스 디바이스 드라이버

app 실행

Page 39: 리눅스 디바이스 드라이버

dmesg