• 검색 결과가 없습니다.

디바이스 드라이버 프로그램

문서에서 GettingStarted-with-HBE-EMPOSII (페이지 84-89)

8. 디바이스 드라이버

8.1. 디바이스 드라이버 프로그램

ssize_t (*read) (…);

ssize_t (*write) (…);

int (*open) (…);

int (*release) (…);

;

File Operation

int init_module(void) { … 모듈 설치시 초기화 수행

void cleanup_module(void) { … 모듈 제거시반환 작업수행

위의 함수들에서 동작 해야 할 내용을 간략하게 설명하면 다음과 같다. 처음으로 디바이 struct file_operations { struct module *owner;

loff_t (*llseek) (struct file *, loff_t, int);

ssize_t (*read) (struct file *, char *, size_t, loff_t *);

ssize_t (*write) (struct file *, const char *, size_t,loff_t *);

int (*readdir) (struct file *, void *, filldir_t);

unsigned int (*poll) (struct file *,struct poll_table_struct *);

int (*ioctl)(struct inode *,struct file *,unsigned int, unsigned long);

int (*mmap) (struct file *, struct vm_area_struct *);

int (*open) (struct inode *, struct file *);

int (*flush) (struct file *);

int (*release) (struct inode *, struct file *);

int (*fsync) (struct file *, struct dentry *, int datasync);

int (*fasync) (int, struct file *, int);

int (*lock) (struct file *, int, struct file_lock *);

ssize_t (*readv)(struct file *,const struct iovec *,unsigned long,loff_t

*);

ssize_t (*writev)(struct file*,const struct iovec *,unsigned long,loff_t

*);

ssize_t (*sendpage)(struct file *,struct page *, int, size_t, loff_t

*,int);

unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);

;

8.1.2 디바이스 드라이버의 커널 삽입 과정

아래와 같은 명령을 이용하여 디바이스 드라이버를 커널에 삽입한다.

[root@EMPOS/root]$ insmod driver.o

여기서 driver.o는 테스트로 작성된 디바이스 드라이버 파일명이다. file_operations 구조체를 커널 변수인 chrdevs에 등록한다.

위와 같이 디바이스 드라이버를 커널에 삽입했으면 다음 해야 하는 일은 드라이버에 대응 하는 특수 장치 파일(노드)을 만드는 일이다.

다음은 콘솔에서 특수 장치 파일을 만드는 명령이다.

[root@EMPOS/root]$ mknod /dev/device c 주번호 부번호

위의 명령에 의해 커널에서 수행 되는 일은 다음과 같다. mknod 명령은 커널의 sys_mknod()를 호출하고 이 함수는 다음과 같은 일을 수행한다.

1. 먼저 /(루트)에서 시작해서 dev 디렉터리까지의 경로를 찾아 ledioport라는 이름의 dentry를 만들고 루트에 연결한다.

2. inode 하나를 만들고 dentry의 d_inode에 연결한다.

3. inode의 i_mode와 i_rdev에 S_IFCHR 과 (주번호<<8|부번호)을 기록한다.

4. inode의 i_fop에 def_chr_fops의 주소 값을 기록하여 이를 통해 open메소드에

int init_module(void) {

printk("Hello, Kernel! n");

return 0;

void cleanup_module(void) {

printk("Good-bye, Kernel! n");

위는 아주 간단한 예로 드라이버가 커널로 로드 될 때 init_module()이 호출되는 콘솔에

“Hello, Kernel!”이 쓰여지고 드라이버가 커널에서 제거될 때 cleanup_module()이 호출되 어 콘솔에 “Good-bye, Kernel!”이 쓰여지는 것을 볼 수 있다.

- Makefile

# Device Driver Makefile

CC = arm-linux-gcc

KERNELDIR = /usr/local/linux-2.4.19-rmk4-pax2-empx1 INCLUDEDIR = -I$(KERNELDIR)/include -I./

CFLAGS = -D__KERNEL__ -DMODULE -Wall -O2 -I$(INCLUDEDIR)

MODULE_OBJS = hello.o MODULE_SRCS = hello.c

$(MODULE_OBJS) :

$(CC) $(CFLAGS) -c $(MODULE_SRCS)

clean:

디바이스 드라이버는 커널에서 사용하는 변수와 함수들을 사용 할 수 있으므로 위에서 보 듯이 커널에 대한 참조가 필요하고, 디바이스 드라이버가 커널에 로드 되어 동작하기 위 해서는 D__KERNEL__와 DMODULE 인수가 필요하다. 나머지 인수들은 커널 전용이 아니 라 일반 gcc 컴파일에서 수행하는 최적화 정도를 알려준다.

호스트 PC에서 아래와 같이 컴파일 해 hello.o파일을 만든다 make

아무런 문제가 발생하지 않으면 디렉토리 안에 hello.o라는 파일들이 생길 것이다. 만약 위의 소스와 똑 같은데 컴파일 에러가 발생한다면 host pc에서 타겟 보드의 커널이 위치 와 Makefile에서 참조하는 커널의 위치가 같은지 체크를 한번 하도록 한다. 그 다음으로 위에서 만들어진 파일(hello.o)파일을 타겟 보드로 시리얼 등을 통해 전송 후. 다음의 명 령으로 hello.o 파일을 커널에 삽입한다.

[root@EMPOS/root]$ insmod hello.o Using hello.o

Hello, Kernel!

위와 같이 hello.o 파일이 커널에 삽입 시 커널이 init_moudle()을 호출하여 콘솔상에 Hello, Kernel! 이라는 문구가 나타난다.

모듈 삽입이 완료되면 lsmod를 통해 커널에 로드 된 모듈을 살펴볼 수 있다 [root@EMPOS/root]$ lsmod

Module Size Used by

hello 216 0 (unsed)

로드 된 모듈을 다음과 같이 rmmod명령을 통해 해제를 하게 된다 [root@EMPOS/root]$ rmmod hello

Good-bye, Kernel!

[root@EMPOS/root]$

rmmod를 통해 커널이 hello.o 모듈을 제거하면서 cleanup_module()을 호출 하여

“Good-bye, Kernel!”라는 문구를 출력한다.

문서에서 GettingStarted-with-HBE-EMPOSII (페이지 84-89)