디바이스 드라이버

32
디디디디 디디디디 디디디디 디디디디 디디디디 디디디디디 디디 디디디디 디디디 디디디디

description

디바이스 드라이버. 디바이스 드라이버에 대한 일반적인 개요를 살펴본다. 목 차. (1) Linux Kernel Module Programming (2) Device Driver 정의 (3) Device Driver 종류 (4) Device Driver 작성 (5) 제작한 Device Driver 검증 파일 만들기 (6) Makefile 만들기 (7) Driver 를 커널에 모듈로 등록 및 해제하기. Kernel Module 정의 (1). 리눅스 커널 (Linux Kernel) - PowerPoint PPT Presentation

Transcript of 디바이스 드라이버

Page 1: 디바이스 드라이버

디바이스 드라이버디바이스 드라이버

디바이스 드라이버에 대한 일반적인 개요를 살펴본다

Page 2: 디바이스 드라이버

2

(1) Linux Kernel Module Programming

(2) Device Driver 정의

(3) Device Driver 종류

(4) Device Driver 작성

(5) 제작한 Device Driver 검증 파일 만들기

(6) Makefile 만들기

(7) Driver 를 커널에 모듈로 등록 및 해제하기

목 차목 차

Page 3: 디바이스 드라이버

3

리눅스 커널 (Linux Kernel) 모노리스 커널 (Monolithic Kernel)

cf) 마이크로 커널 (Micro-kernel) 커널의 기능을 확장하기 위해서는 커널 재컴파일이 필요

커널 모듈 (Kernel Module) 실행시간에 커널을 확장하기 위해 사용하는 오브젝트 모듈 커널이 실행중인 동안에 동적으로 로딩하여 커널과 링크함으로써 커널의

기능을 확장하여 사용할 수 있으며 , 불필요 시에 커널과의 링크를 풀고 메모리에서 제거할 수 있다 커널 재컴파일이 필요없이 커널 기능 확장이 가능

명시적인 커널 모듈 설치 및 제거 과정이 필요 Insmod / rmmod 명령어

디바이스 드라이버 , 파일시스템 , 네트워크 프로토콜 스택 등에 적용 커널 경량화를 위해 반드시 필요 임베디드 시스템의 경우 , 제한적인 자원으로 인해 커널 등 시스템

소프트웨어의 최소화가 필요

Kernel Module Kernel Module 정의 정의 (1)(1)

Page 4: 디바이스 드라이버

4

커널 모듈 프로그래밍 커널 모듈은 커널 모드에서 실행됨으로 커널 프로그래밍에 준하여

작성되어야 한다 모듈 프로그래밍의 주의 사항

무제한적인 메모리 접근 메모리 접근 오류는 시스템에 치명적인 손상을 줄 수 있음

커널 함수 호출에 따른 에러 코드 검사 실수 연산 및 MMX 연산 사용 불가 제한적인 커널 스택 크기

크기가 큰 배열 사용 회피 동적 할당 방법을 이용 재귀 호출 회피

상이 플랫폼 고려 32 bit 및 64 bit 환경 바이트 순서 – big-endian 또는 little-endian 프로세서에 특화된 명령어 사용 회피

버전 종속성 커널 버전에 따라 모듈 버전이 다름

Kernel Module Kernel Module 정의 정의 (2)(2)

Page 5: 디바이스 드라이버

5

커널 모듈 버전 종속성 (Version Dependency) 커널 버전에 따라 지원되는 커널 함수의 종류나 프로토 타입이 다르기

때문에 다른 버전의 커널에 모듈을 링크하려면 모듈 재컴파일이 필요 모듈을 커널에 설치할 때에 버전 검사 수행

커널 버전과 모듈 버전이 일치하지 않는 경우에 모듈을 설치할 수 없음 커널 모듈 프로그램의 버전 정의

커널 ver.2.0 이상에서는 <linux/module.h> 헤드 파일에서 char kernel_version[ ] 변수에 커널 버전을 정의

커널 모듈 프로그램에서 위의 헤드 파일을 including

#include <linux/module.h> 커널 버전 정의는 전체 모듈에서 한번만 정의되어야 함

커널 버전에 따른 종속적인 동작 정의 <linux/version.h> 에서 정의된 매크로 LINUX_VERSION_CODE 사용

#ifdef LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) // 리눅스 ver.2.4.0 이상일 때의 코드 #else // 리눅스 ver.2.4.0 미만일 때의 코드 #endif

Kernel Module Kernel Module 정의 정의 (3)(3)

Page 6: 디바이스 드라이버

6

커널 모듈 구성 커널 기능을 확장한 함수와 자료 구조로 구성

main() 함수는 없는 독립된 프로그램 모듈 init_module()/cleanup_module() 함수 존재

init_module() 함수 모듈이 설치될 때에 자동적으로 호출 모듈 초기화 등의 기능 수행

cleanup_module() 함수 모듈을 삭제할 때에 자동적으로 호출 모듈 제거에 따른 cleanup 작업을 수행

기본적인 구성

Kernel Module Kernel Module 작성 작성 (1)(1)

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/init.h>

/* global variables */

int init_module(void) { }

void cleanup_module(void) { }

Page 7: 디바이스 드라이버

7

커널 모듈 구성 ( 계속 )

커널 ver.2.4 이상에서는 module_init() / module_exit() 매크로 지원

함수 이름에 의한 종속 관계를 해결 module_init() 매크로 : startup 함수 등록 module_exit() 매크로 : cleanup 함수 등록

Kernel Module Kernel Module 작성 작성 (2)(2)

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/init.h>

/* global variables */

int module_start() { /* 모듈이 설치될 때에 초기화를 수행하는 코드 */ }

int module_end() { /* 모듈이 제거될 때에 반환작업을 수행하는 코드 */ }

module_init(module_start);

module_exit(module_end);

Page 8: 디바이스 드라이버

8

커널 모듈 구성 ( 계속 )

모듈 프로그램의 Makefile -c : 링커를 호출하지 않고 오브젝트 모듈만 생성 -O : 최적화 옵션 지정 ( 최대 O2) 컴파일 매크로 : __KERNEL__ , MODULE, LINUX

Kernel Module Kernel Module 작성 작성 (3)(3)

CC = arm_linux_gcc

INCLUDEDIR = /kernel_source_dir/include

CFLAGS := -c -O –Wall –D__KERNEL__ –DMODULE –DLINUX -I$(INCLUDEDIR)

OBJS = hello.o

all : $(OBJS)

clean : rm –f *.o *.~커널

프로그램임을 명시하는 매크로

모듈 프로그램임을

명시하는 매크로

Linux 플랫폼에서 동작하는 모듈임을

정의하는 매크로

Page 9: 디바이스 드라이버

9

커널 모듈 설치 및 제거 관련 쉘 명령어

Kernel Module Kernel Module 설치 및 제거 설치 및 제거 (1)(1)

이 름 용 도

insmod module 을 설치 (install)

rmmod 실행중인 modules 을 제거 (unload)

lsmod Load 된 module 들의 정보를 표시

depmodModule 들의 symbol 들을 이용하여 Makefile 과 유사한 dependency file 을 생성

modprobedepmod 명령으로 생성된 dependency 를 이용하여 지정된 디렉토리의 module 들과 연관된 module 들을 자동으로 load

modinfo 목적화일을 검사해서 관련된 정보를 표시

Page 10: 디바이스 드라이버

10

커널 모듈 설치 및 제거 ( 계속 )

설치된 모듈은 ‘ /proc/modules’ 파일에 기록된다 ‘/proc/modules’ 파일을 이용한 현재 설치된 모듈을 확인 가능

#cat /proc/modules

Kernel Module Kernel Module 설치 및 제거 설치 및 제거 (2)(2)

Page 11: 디바이스 드라이버

11

커널 모듈 프로그램 작성 모듈 적재 및 제거 시에 간단한 메시지를 출력하는 모듈 작성 구현 방법

모듈 적재 시에 호출되는 init_module() 함수에서 printk() 함수를 이용하여 “ Hello, World!” 메시지를 출력한다

모듈 제거 시에 호출되는 cleanup_module() 함수에서 같은 방법으로 “ Good bye!!!” 메시지를 출력한다

모듈 작성 및 테스트1. 모듈 프로그램 소스 파일 hello_world.c 을 작성한다

Kernel Module Kernel Module 프로그래밍 프로그래밍 (1)(1)

/* hello_world.c */

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/init.h>

static int module_begin(void)

{

printk(“Hello, World!\n”);

return 0;

}

static void module_end(void){ printk(“Good bye!!!\n”);}

EXPORT_NO_SYMBOLS;module_init(module_begin);module_exit(module_end);

Page 12: 디바이스 드라이버

12

커널 모듈 프로그램 작성 ( 계속 )

모듈 작성 및 테스트2. Makefile 을 작성하고 컴파일을 수행한다

3. Hello_world.o 모듈을 임베디드 시스템에 다운로드한다4. 임베디드 시스템에서 모듈 설치 및 제거를 수행

# insmod hello_world.o

# lsmod

# rmmod hello_world

# lsmod

Kernel Module Kernel Module 프로그래밍 프로그래밍 (2)(2)

# Makefile

CROSS_COMPILE=arm_linux_gcc

INCLUDEDIR = /kernel_source_dir/include

MODCFLAGS = -c -O –Wall –D__KERNEL__ -DMODULE –DLINUX -I$(INCLUDEDIR)

SRC = hello_world.c

hello_world.o: $(SRC)

$(CROSS_COMPILE) $(MODCFLAGS) $(SRC)

Page 13: 디바이스 드라이버

13

물리적인 hardware 장치를 다루고 관리하는 software user application 이 driver 에게 요청을 하면 , driver 는 hardware

를 구동시켜서 목적을 달성 major number 와 minor number 를 이용하여 각각의 devices 을

구분하여 사용 device 와 system memory 간에 data 의 전달을 담당하는 kernel

내부 기능

Device Driver Device Driver 정의 정의 (1)(1)

Page 14: 디바이스 드라이버

14

Kernel

Device Driver Device Driver 정의 정의 (2)(2)

task

System call interface

File system

Block Driver

task task

Char Driver

DDI (device driver interface)

task

Network Driver

terminal keyboard Hard disk CD-ROM ethernet

User application

level

Kernel level

Hardware level

Page 15: 디바이스 드라이버

15

Device Driver Device Driver 종류종류

Driver종류 설 명

Char Driver

device 를 file 처럼 취급하고 접근하여 직접 read/write를 수행 , data 형태는 stream 방식으로 전송EX) console, keyboard, serial port driver 등

Block Driver

disk 와 같이 file system 을 기반으로 일정한 blcok 단위로 data read/write 를 수행EX) floppy disk , hard disk, CD-ROM driver 등

Network Driver

network 의 physical layer 와 frame 단위의 데이터를 송수신EX) Ethernet device driver(eth0)

등록함수명

register_chrdev()

register_blkdev()

register_netdev()

Page 16: 디바이스 드라이버

16

기본적인 device driver 의 형태

Device Driver Device Driver 작성 작성 (1)(1)

Device Opertations

static struct file_operations device_fops={

open : device_open,

release : device_release,

read : device_read,

write : device_write,};

Function Prototypes

static int device_open();

static int device_release();

ssize_t device_read();

static ssize_t device_write();

int init_function();

void cleanup_function();

Module 제거 시 반환작업 수행 module_exit(cleanup_function)

Module 설치 시 초기화 수행 module_init(init_function)

Header Files

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/init.h>

Printf 와 같은 기능의 커널 코드를 위한 함수

필요한 header. 모듈소스가 include

해야함

insmod 로 모듈을 적재하면 이 함수가 불려진다 . 이 함수 안에서 regiseter_chrdev() 커널 함수를

뷸러서 모둘을 적재한다 .

rmmod 로 적재된 모듈을 삭제할 경우 이 함수가

불려진다 . unregister_chrdev() 커널 함수를 불려서

모듈을 삭제한다 .

“ 파일시스템”헤더는 디바이스 드라이버를

쓰는데 필요한 헤더파일

application 에서 쓰는 함수와 driver 에서 쓰는

함수를 mapping

Module_init() 과 module_exit() 정의됨

Page 17: 디바이스 드라이버

17

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/kernel.h>

#include <linux/init.h>

#define DEV_NAME "test_dd"

int test_major = 0;

int result;

///////////// 함 수 정 의 //////////////

int device_open (struct inode *inode, struct file *filp);

int device_release (struct inode *inode, struct file *filp);

ssize_t device_read (struct file *filp, unsigned int *buf, size_t count, loff_t *f_pos);

ssize_t device_write (struct file *filp, unsigned int *buf, size_t count, loff_t *f_pos);

int device_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned int arg);

int sample_init();

void sample_cleanup();

Device Driver Device Driver 작성작성 (2)(2)

모듈을 커널에 적재하는 함수 register_chrdev() 의 parameter 로써 0 으로 설정하면 major 값을 뒤에서부터 자동으로 빈자리로 등록시킨다

register_chrdev() 함수가 return 하는 값을 넘겨받음 . 0 보다 적으면 모듇 등록 실패

application 에서 kernel 로부터 넘어온 값을 처리하는 함수

application 에서 open() 함수로 driver 를 호출할때 실행되는 함수

application 에서 close()함수로 driver 를 닫을때

실행되는 함수

Page 18: 디바이스 드라이버

18

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

{

printk("test_open start!!!\n");

MOD_INC_USE_COUNT;

return 0;

}

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

{

MOD_DEC_USE_COUNT;

return 0;

}

ssize_t device_read (struct file *filp, unsigned int *buf, size_t count, loff_t *f_pos)

{

printk("read() ^^\n");

return 0;

}

ssize_t device_write (struct file *filp, unsigned int *buf, size_t count, loff_t *f_pos)

{

return 0;

}

Device Driver Device Driver 작성 작성 (3)(3)

이 함수가 호출될때마다 count 가 증가한다 .

이 함수가 호출될때마다 count 가 감소한다 .

Application 에서 read 함수를 호출하면 terminal 에 문자 출력

Page 19: 디바이스 드라이버

19

int device_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned int arg)

{

printk("ioctl() ^^\n");

return 0;

}

struct file_operations test_fops = {

open: device_open,

read: device_read,

write: device_write,

ioctl: device_ioctl,

release: device_release,

};

module_init(sample_init);

module_exit(sample_cleanup);

Device Driver Device Driver 작성 작성 (4)(4)

Ioctl() 호출이 성공하면 문자 출력

파일연산구조체는 char device driver 에 대한 모든 연산을 포함한다 . 즉 여기에 정의된

함수를 통해서 커널이 접근하게 된다 . 즉 application 에서 open 함수를 호출하면 이는 dri

ver 의 test_open() 과 mapping 되어있어 이를 실행하게 된다 .

insmod로 불려지는 함수

rmmod로 불려지는 함수

Page 20: 디바이스 드라이버

20

int sample_init(void)

{

result = register_chrdev(test_major, DEV_NAME, &test_fops);

if (result < 0) {

printk(KERN_WARNING "%s: can't get major %d\n", DEV_NAME, test_major);

return result;

}

printk("<1> init module success!!.. %s major number : %d\n", DEV_NAME, result);

return 0;

}

void sample_cleanup(void)

{

if( !unregister_chrdev(result, DEV_NAME) )

printk("%s cleanup_module success...\n", DEV_NAME);

else

printk("%s cleanup_module fail...\n", DEV_NAME);

}

Device Driver Device Driver 작성 작성 (5)(5)

driver 를 커널에 모듈로 등록하는 함수 , result 에

major 값이 넘어옴

driver 를 커널에서 삭제하는 함수

Page 21: 디바이스 드라이버

21

#include <stdio.h>

#include <fcntl.h>

#include <string.h>

#include <errno.h>

int fd;

int main(int argc, char **argv)

{

if( (fd = open("/dev/testdd", O_RDWR)) < 3) {

fprintf(stderr, "/dev/testdd device file open error!! .. %s\n",strerror(errno));

return 0;

}

read(fd, 0, 0);

ioctl(fd, NULL,0);

close(fd);

return 0;

}

Device Driver Device Driver 검증 프로그램 만들기검증 프로그램 만들기 (1)(1)

mknod 를 통하여 /dev 에 만들어진 node(file) 을 open 한다 .

File 에 대한 제어와 설정

Error 에 관한 header file

Page 22: 디바이스 드라이버

22

Compile Options

%arm-linux-gcc –c –D__KERNEL__ -DMODULE –Wall –o2 –o test_dd.o test_dd.c

Device Driver Device Driver 검증 프로그램 만들기검증 프로그램 만들기 (2)(2)

모듈은 test_dd.o로 컴파일 되어야 하므로 – c 옵션

사용

test_dd 는 커널에서 동작하고 모듈에 사용된다는 뜻

경고를 다 출력해준다는

의미

Compile 과정에서 inlne 함수를 확장할

때 최적화함

Page 23: 디바이스 드라이버

23

CC =arm-linux-gcc

INCLUDEDIR = /usr/local/pza255/linux-2.4.19-huins/include

CFLAGS = -D__KERNEL__ -DMODULE -Wall -O2

CFLAGS2 = -I.. -I$(INCLUDEDIR)

All: test_dd test_app

test_dd : test_dd.c

$(CC) $(CFLAGS) $(CFLAGS2) -c -o test_dd.o test_dd.c

test_app : test_app.c

$(CC) -o test_app test_app.c

clean :

rm -rf test_dd.o test_app

Device Driver Device Driver 검증 프로그램 만들기검증 프로그램 만들기 (3)(3)

Macro 부분 C 에서 define 역할

Command 부분파일들의 dependency 를 설정

targetcommand

주의할 점은 이 공백은 반드시

Tab 공백

Page 24: 디바이스 드라이버

24

Char Device Driver 등록 방법 외부와 device driver 는 file interface (node 를 의미 ) 를 통해 연결 Device driver 는 자신을 구별하기 위해 고유의 major number 를 사용

장치의 등록과 해제 등록 : int register_chrdev(unsigned int major, const char

*name, stuct file_operations *fops) Major : 등록할 major number. 0 이면 사용하지 않는 번호 중 자동으로

할당 Name : device 의 이름 Fops : device 에 대한 file 연산 함수들

해제 : int unregister_chrdev(unsigned int major, const char *name)

Device Driver Device Driver 등록 및 해제 등록 및 해제 (1)(1)

Page 25: 디바이스 드라이버

25

Device Driver Device Driver 등록 및 해제 등록 및 해제 (2)(2)

kernel

device driver

file operations device_open device_close device_read device_write

systemcall

userprogram

openclosereadwrite

device

Page 26: 디바이스 드라이버

26

Major number 와 minor number

장치를 구분하는 방법으로 둘을 이용하여 특정 장치를 구별

Major number : 커널에서 디바이스 드라이버를 구분하는데 사용

Minor number : 디바이스 드라이버 내에서 필요한 경우 장치를 구분하기 위해 사용

새로운 디바이스는 새로운 major number 를 가져야 함

register_chrdev() 로 장치를 등록할 때 major number 를 지정

같은 major number 가 등록되어 있으면 등록 실패

Major 와 minor 번호는 파일의 정보를 담고 있는 inode 의 i_rdev

에 16bit 로 저장된다 . 상위 8bit 는 major, 하위 8bit 는 minor

이다 .

Device Driver Device Driver 등록 및 해제 등록 및 해제 (3)(3)

Page 27: 디바이스 드라이버

27

mknod 명령으로 디바이스 드라이버에 접근할 수 있는 장치 파일

생성 mknod [device file name] [type] [major] [minor]

Ex] %mknod testdd c 252 0

mdev_t : 장치의 major, minor number 를 표현하는 자료구조 MAJOR() : kdev_t 에서 major number 를 얻어내는 매크로

Ex] MAJOR(inode->i_rdev);

MINOR() : kdev_t 에서 minor number 를 얻어내는 매크로

cat /proc/devices 명령으로 현재 로드된 디바이스 드라이버 확인

C 는 char device drive 의미 , block device drive 는 b 를 사용

Device Driver Device Driver 등록 및 해제 등록 및 해제 (4)(4)

Page 28: 디바이스 드라이버

28

/usr/lcoal/pxa255/linux-2.4.19-cd/include/linux/fs.h

앞에서 작성했던 driver 에 사용된 파일연산 함수

Device Driver Device Driver 등록 및 해제 등록 및 해제 (5)(5)

Page 29: 디바이스 드라이버

29

이 름 용 도

insmod module 을 설치 (install)

rmmod 실행중인 modules 을 제거 (unload)

lsmod Load 된 module 들의 정보를 표시

depmodModule 들의 symbol 들을 이용하여 Makefile 과 유사한 dependency file 을 생성

modprobedepmod 명령으로 생성된 dependency 를 이용하여 지정된 디렉토리의 module 들과 연관된 module 들을 자동으로 load

modinfo 목적화일을 검사해서 관련된 정보를 표시

Device Driver Device Driver 등록 및 해제 등록 및 해제 (6)(6)

Page 30: 디바이스 드라이버

30

Device Driver 의 동작 과정

Device Driver Device Driver 등록 및 해제 등록 및 해제 (7)(7)

Page 31: 디바이스 드라이버

31

앞에서 만든 드라이버 소스를 test_dd.c, test application 은 test_app.c, 그리고 makefile 은 Makefile 로 작성 후 저장한다 .

make 명령어를 이용하여 위의 2 files 을 컴파일한다 .% make

생성된 test_dd.o 와 test_app 를 target 으로 전송한다 . 전송방식은 앞에서 배웠던 minicom 또는 nfs 방식을 이용한다 . 밑에서는 nfs 방식을 통하여 파일을 전송하였다 .

Device Driver Device Driver 등록 및 해제 등록 및 해제 (8)(8)

Page 32: 디바이스 드라이버

32

Module 을 kernel 에 적재 major

number는 253

Test application 에서 open() 로 이 nod 를 연다 . 이 nod 로 application

과 hardware 가 만남

ls 명령으로 nod 가 잘 만들어졌는지 확인 . 253 은 m

ajor 번호

결과 화면

Device Driver Device Driver 등록 및 해제 등록 및 해제 (9)(9)