280 likes | 497 Views
운영체제 개론 및 실습. 단국대학교 정보 컴퓨터학부 2007 년 1 학기 최종무 choijm@dku.edu http://embedded.dankook.ac.kr/~choijm. Linux Device Driver. Device. Memory Mapped I/O. 주소공간 (1G). Device. 물리 메모리 (1G). 장치 자체. 물리 메모리 3byte. I/O Mapped I/O. 레지스터. command. 장치 Controller. status. control. 주소공간 (1G).
E N D
운영체제 개론 및 실습 단국대학교 정보 컴퓨터학부 2007년 1학기 최종무 choijm@dku.edu http://embedded.dankook.ac.kr/~choijm
Device Memory Mapped I/O 주소공간(1G) Device 물리 메모리(1G) 장치 자체 물리 메모리 3byte I/O Mapped I/O 레지스터 command 장치 Controller status control 주소공간(1G) 물리 메모리(1G) 주소공간(3byte)
Driver File Operations Init Open Read Write Close xxx_init() xxx_exit() Driver H/W register 접근 루틴
Device Driver • Device Driver • 시스템이 지원하는 하드웨어를 응용 프로그램에서 사용 할 수 있도록 커널 상에서 제공하는 라이브러리 • System Call 방식 • 소프트웨어 인터럽트 이용 응용 프로그램의 요청을 커널이 수행 • 초기 운영체제 설계 방식 • 하드웨어 증가에 따른 개발 부담 증가 • File Type Device Driver • 파일 입출력 함수로 하드웨어를 제어 • 일반 파일을 제어하듯 하드웨어를 표현
Device Driver • Modules • 초기 리눅스에 커널 소스에 모듈을 포함 하는 방식사용 • 커널 컴파일 시간의 오버헤드 • 커널 동작중 디바이스 드라이버 동적으로 추가/제거 개념 도입 • 커널 자원의 효율적 이용성 증가 • Device file • 디바이스 드라이버를 이용시 하드웨어와 연관된 개념 필요 • 실질적인 장치를 나타내는 디바이스 파일 존재(/dev/) • 디바이스 파일의 정보 • 주 번호 : 응용 프로그램과 디바이스 드라이버의 연결 • 부 번호 : 처리하고자 하는 실질적인 디바이스 • mknod 사용 하여 디바이스 파일 생성
Device Driver • Device Driver 종류 • Character Device Driver • open(), close(), read(), write() 사용 • 스트림 지향적 • Block Device Driver • 응용프로그램에서 직접 사용 안함 • 파일 시스템을 통해 접근 • 일반적으로 1KByte 사용
File I/O 기본함수 #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> int open ( const char *pathname, int oflag, … /*, mode_t mode */); • 기능 : 파일이나 물리적인 장치와 file descriptor를 연결해준다. #include <unistd.h> int close ( int filedes); • 기능: 열려진 파일을 닫는다. #include <unistd.h> ssize_t read (int filedes, void *buf, size_t nbytes); • 기능: 파일로 부터 데이터를 읽어 들이는 함수 (파일 offset 증가) #include <unistd.h> ssize_t write (int filedes, const void *buf, size_t nbytes); • 기능: 지정된 파일에 데이터를 쓰는 함수 (파일 offset 증가)
Device file 명령 • 기능 : 특수 파일을 만든다. • 옵션 • -m, --mode mode: 생성된 파일의 모드를 지정하는 옵션이다. mode 로 사용할 것은 chmod 에서 사용하는 기호나 숫자 형식 • --help:도움망을 보여주고 마친다 • --version:버전 정보를 보여준다 #mknod [options] 디바이스 파일명 {bcu} 주번호 부번호 옵션 : [-m mode] [--mode=mode] [--help] [--version]
모듈 개념 사용자 영역 커널 영역 적재 모듈 제거
Module 관련 명령 • 기능 : 커널의 심볼 테이블 시스템을 통해 모듈로 작성한 커널 에 링크 시키도록 도와주는 명령 • 옵션 • -f:현재 실행중인 커널과 모듈의 컴파일된 커널의 버전이 다르더라도 모듈을 적재한다 • -k:모듈의 auto-clean 플래그를 설정한다 • -m:커널 패닉 상태일 때 로드맵을 출력해서 모듈을 디버그하기 쉽게 한다. • -o:소스 객체 파일의 기본 이름에서 모듈명을 끌어내지 않고, 직접 모듈 이름을 지정한다 • -s:syslog에 출력한다 • -v:실행되는 과정에서 발생한 메시지를 모두 출력한다 #insmod [0fkmpsxXv] [-o module_name] object_file [symbol=value]
Module 관련 명령 #rmmod [-f] [-w] [-s] [-v] [modulename] • 기능 : 커널에 등록된 모듈을 제거하는 명령 • 옵션 • -v –verbose:실행과정에서 발생한 메시지를 모두 출력한다 • -f –force:모듈이 제거될 수 없는 상황에서도 강제 제거한다 • -w –wait:모듈이 제거될 수 있는 상황이 될 때까지 기다렸다가 제거 한다 • -s:syslog에 출력한다 #lsmod • 기능 : 커널에 등록된 모듈의 상태를 보여준다
예제 1(module_basic.c) • module_basic.c #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");
예제 1(Makefile) • Makefile obj-m := test.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: rm -rf *.ko rm -rf *.mod.* rm -rf .*.cmd rm -rf *.o
장치파일 등록(1/2) • 장치 파일 등록 [root]# insmod mydrv_dev.ko int rdwr_init(void) { int result; result = register_chrdev(RDWR_DEV_MAJOR, RDWR_DEV_NAME, &rdwr_fops); ….. return 0; } module_init(rdwr_init);
장치파일 등록(2/2) • register_chrdev 의 기능 쉘 디바이스 드라이버 커널 Chr_devs Block_devs xxx_init(…) { register_chrdev( D_name, 240, fops); } … [root]# insmod mydrv.ko … index
Open 의 이해 • Open 과정 응용프로그램 task_structure open( /dev/mydrv ); files open(); 커널 디바이스 드라이버 Chr_devs open(); struct file_operations mydrv_fops = { .read = mydrv_read, .write = mydrv_write, .open = mydrv_open, .release = mydrv_release, }; inode i_mod = S_IFCHR i_rdev = 240:0 HDD Block_devs
예제 1(call_dev.c)(1/4) • call_dev.c #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/types.h> #include <linux/fcntl.h> #define CALL_DEV_NAME "calldev" #define CALL_DEV_MAJOR 240 int call_open(struct inode *inode, struct file *filp){ int num = MINOR(inode->i_rdev); printk("call open -> minor : %d\n", num); return 0; }
예제 1(call_dev.c)(2/4) • call_dev.c loff_t call_llseek (struct file *filp, loff_t off, int whence){ printk("call llseek -> 0ff: %08X, whence : %08X\n", off, whence); return 0x23; } ssize_t call_read(struct file *filp, char *buf, size_t count, loff_t *f_pos){ printk("call read -> buf : %08X, count : %08 \n", buf, count); return 0x33; } ssize_t call_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos){ printk("call write 0> buf : %08X, count : %08X \n", buf, count); return 0x43; } int call_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ printk("call ioctl -> cmd : %08X, arg : %08X \n", cmd, arg); return 0x53; }
예제 1(call_dev.c)(3/4) • call_dev.c int call_release (struct inode *inode, struct file *filp){ printk("call release \n"); return 0; } struct file_operations call_fops= { .llseek = call_llseek, .read = call_read, .write = call_write, .ioctl = call_ioctl, .open = call_open, .release = call_release, };
예제 1(call_dev.c)(4/4) • call_dev.c int call_init(void){ int result; printk("call call_init\n"); result = register_chrdev(CALL_DEV_MAJOR, CALL_DEV_NAME, &call_fops); if(result<0) return result; return 0; } void call_exit(void){ printk("call call_exit \n"); unregister_chrdev(CALL_DEV_MAJOR, CALL_DEV_NAME); } module_init(call_init); module_exit(call_exit); MODULE_LICENSE("DUAL BSD/GPL");
예제 1(call_app.c)(1/3) • call_app.c #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #define DEVICE_FILENAME "/dev/calldev" int main(){ int dev; char buff[128]; int ret; printf("1) device file open\n"); dev = open(DEVICE_FILENAME, O_RDWR|O_NDELAY);
예제 1(call_app.c)(2/3) • call_app.c if(dev>=0) { printf("2) seek function call\n"); ret = lseek(dev, 0x20, SEEK_SET); printf("ret = %08X\n",ret); printf("3) read function call\n"); ret = read(dev,0x30, 0x31); printf("ret = %08X\n", ret); printf("4) write function call\n"); ret = write(dev, 0x40, 0x41); printf("ret = %08X\n",ret);
예제 1(call_app.c)(3/3) • call_app.c printf("5) ioctl function call\n"); ret = ioctl(dev, 0x51, 0x52); printf("ret = %08X\n" ,ret); printf("6) device file close\n"); ret = close(dev); printf("ret = %08X\n" ,ret); } return 0; }