400 likes | 646 Views
이식성과 데이터형. 서로 다른 프로세서 상에서의 이식성을 위해 가급적 리눅스 커널이 제공하는 데이터형을 사용하는 것이 좋다 . #include <asm/types.h> 에 정의 . 주로 사용되는 데이터형. 동적 메모리 할당 함수. kmalloc(), kfree()-1. 메모리주소 kmalloc( 할당 받을 크기 , 옵션 ); kfree( 메모리주소 ); * 할당 가능한 최대 크기는 32 x PAGE_SIZE ( 일반적으로 128KB) #include <linux/slab.h>
E N D
이식성과 데이터형 • 서로 다른 프로세서 상에서의 이식성을 위해 • 가급적 리눅스 커널이 제공하는 데이터형을 • 사용하는 것이 좋다. • #include <asm/types.h>에 정의. • 주로 사용되는 데이터형
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); }
kmalloc(), kfree()-2 메모리 할당 시 사용되는 옵션 (할당된 메모리에 특성을 주거나 할당 시점에 처리방식을 지정)
vmalloc(), vfree() 메모리주소 vmalloc(할당 받을 크기); vfree(메모리주소); #include <linux/vmalloc.h> char *buf; buf = vmalloc(1024); if (buf != NULL) { … vfree(buf); }
vmalloc(), vfree() 특징 • 가상 주소 공간에서 할당받기 때문에 해당주소의 영역이 • 하드디스크에 있을 수도 있어 실패할 수 있다. • 커다란 연속된 공간을 할당하기 위해 가상메모리 관리 루틴이 • 수행되기 때문에 kmalloc() 보다 속도가 매우 느리다. • 할당 시 프로세스가 잠들지 못하게 할 수 없기 때문에 • 인터럽트 서비스 함수 안에서는 사용할 수 없다.
__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); }
초기화와 종료 처리 • 디바이스 드라이버가 동작하기 위한 초기화와 종료에 필요한 대표적인 처리 항목 • 디바이스 드라이버의 등록과 해제 • 디바이스 드라이버에 내부 구조체의 메모리 할당과 해제 • 여러 프로세스가 하나의 디바이스에 접근할 때 필요한 사전 처리 및 종료 시 처리 • 주 번호에 종속된 부 번호를 관리하기 위한 사전 처리 및 종료 시 처리 • 하드웨어 검출 처리 및 에러 처리 • 응용 프로그램에서 디바이스 드라이버를 사용하는 경우의 처리 및 사용 종료 처리 • 부 번호에 관련된 프로세스별 처리 • 프로세스별 메모리 할당과 해제 • 사용하는 모듈 수의 관리
초기화와 종료 처리 • 디바이스 드라이버 두 가지 초기화 처리시점 1) 모듈 적재와 & 제거과정 -insmod 명령 : module_init – 모듈적재 과정(초기화 처리) -rmmod 명령 : module_exit – 모듈제거 과정(종료처리) 2)응용프로그램이 디바이스 파일을 여는 과정과 닫는 과정 -open( )함수 : file_operation.open – 디바이스 파일을 여는 과정 -close( )함수 : file_operation.release – 디바이스파일을 닫는 과정 • 이중 어디에서 처리해야 된다는 표준 규정은 없다.(하드웨어의 구조와 디바이스 드라이버의 구현 방식에 따라 달리 지기 때문)
초기화와 종료 처리 • module_init 의 초기화 처리 • 디바이스 드라이버의 등록 • 디바이스 드라이버에 내부 구조체의 메모리 할당 • 여러 프로세스가 하나의 디바이스에 접근하는 경우에 사전처리 • 주 번호에 종속된 부 번호를 관리하기 위한 사전 처리 • 하드웨어 검출 처리 및 에러 처리 • 하드웨어 초기화
초기화와 종료 처리 int xxx_init(void) { xxx_probe(… //하드웨어 검출 처리 및 에러처리 xxx_setup(…. //하드웨어 초기화 register_chrdev(… //디바이스 드라이버의 등록 info = kmalloc(… //디바이스 드라이버에 동작에 필요한 내부 구조체의 메모리 할당 xxx_setupinfo(… //여러 프로세가 디바이스 하나에 접근하는 경우에 필요한 사전 처리 xxx_setupminor(… // 주번호에 종속된 부 번호를 관리하기 위한 사전 처리 } module_init 처리순서
초기화와 종료 처리 • module_exit 의종료 처리 • 초기화 시점에 할당된 메모리 모두 반납 (디바이스 드라이버는 커널의 일부이기 때문에 메모리를 자동 반납하지 않는다.) • 디바이스 드라이버의 해제 • 디바이스 드라이버에 할당된 모든 메모리의 해제 • 하드웨어 제거에 따른 처리
초기화와 종료 처리 void xxx_exit(void) { kfree(… // 디바이스 드라이버에 할당된 모든 메모리 해제 unregister_chrdev(… // 디바이스 드라이버의 해제 xxx_shutdown(… //하드웨어 제거에 따른 처리 } module_exit 처리순서
초기화와 종료 처리 • 디바이스 드라이버 open( ) 함수[1] • 반드시 디바이스 드라이버의 주 번호 정보가 있는 파일을 열어야 한다. • Open 함수 호출 시 초기화 처리 • 디바이스 드라이버가 처음 열렸을 때 하드웨어 초기화 • 디바이스 드라이버의 동작에 필요한 에러처리 • 부 번호에 대한 처리가 필요한 경우 파일 오퍼레이션 구조체를 갱신 • 프로세스별 메모리 할당과 초기화 • 모듈의 사용 횟수 증가(커널 2.4) • 커널 2.6에서는 사용횟수 관리를 커널에서 한다.
초기화와 종료 처리 int fd; fd = open( DEVICE_FILENAME, O_RDWR|O_NDELAY); //반드시 주번호 정보가 있는 파일 if( fd < 0 ) { printf (“error number %d\n”, error); exit(1); } #include<linux/fs.h> struct file_operations call_fops = { … .open = xxx_open, … } int xxx_open( struct inode *inode, struct file *filp ) { int err = 0; //open() 시 처리내용들…. return err; } *inode – 열린 디바이스 파일에 대한 정보 *filp – 디바이스 드라이버 처리관련 정보 ENODEV : 하드웨어가 존재하지 않는다. ENOMEM : 커널 메모리가 부족하다. EBUSY : 디바이스가 이미 사용중 이다. • 디바이스 드라이버 open( ) 함수[2]
초기화와 종료 처리 • 디바이스 드라이버 release( ) 함수[1] • release( ) 함수 호출 시 종료 처리 • 프로세스별 할당 메모리 해제 • 모듈 사용 횟수 감소(커널 2.4) • 커널 2.6에서는 사용횟수 관리를 커널에서 한다.
초기화와 종료 처리 if( fd ) close( fd ); #include<linux/fs.h> struct file_operations call_fops = { … .release = xxx_release, … } int xxx_release( struct inode *inode, struct file *filp ) { //close( ) 시 처리내용들…. return 0; } • 디바이스 드라이버 release( ) 함수[2]
모듈 사용 횟수 관리 • 커널 2.4 • MOD_INT_USE_COUNT : 모듈 사용 횟수를 증가시킨다. • MOD_DEC_USE_COUNT : 모듈사용 횟수 감소시킨다. • MOD_IN_USE : 모듈 사용 횟수가 0이 아니면 참값을 반환한다. • 커널 2.6 • Try_module_get(THIS_MODULE) : 모듈 사용 횟수를 증가시킨다. • Module_put(THIS_MODULE) : 모듈사용 횟수 감소시킨다. 모듈 사용횟수 관리 함수
문자 디바이스 드라이버 동작-1 read dev-read 응용 프로그램 장치파일 문자 디바이스 드라이버 하드웨어 return return * 단일 방식의 호출규칙을 통해 다양한 개념과 다양한 형태의 하드웨어를 제어 가능하다
문자 디바이스 드라이버 동작 디바이스 드라이버 하드웨어 인터럽트 insmod xxx_init(); struct file_operations { open : xxx_open write : xxx_write . . . } xxx_exit(); xxx_interupt(); xxx_open(); xxx_write(); 응용 프로그램 open(); write(); rmmod
커널 2.6의 파일 오퍼레이션 구조체 struct file_operations { struct module *owner; int (*open)(struct inode *, struct file *); . . . } * 디바이스 드라이버의 file_operations에서정의되지 않았거나 NULL로 채워진 필드는 커널에 의해서 default 처리를 한다.
문자 디바이스 드라이버의 등록과 해제 및 구성 <linux/fs.h>를 추가하고 int register_chrdev(unsigned int major, const char *name, struct file_operations *fops); 를 이용해 커널에 디바이스 드라이버의 file_operations을 등록한다.(중요!!!) *디바이스 드라이버가 등록된다는 것은 주번호에 연관된 file_operations 구조체가 커널에 등록된다는 의미. int unregister_chrdev(unsigned int major, const char *name); 를 이용해 등록된 디바이스 드라이버를 해제한다. 주번호는 응용 프로그램에서 디바이스 파일을 이용해 디바이스 드라이버를 찾을 때 사용 디바이스 드라이브명은 proc 파일 시스템이나 오류정보를 커널에 나타내기 위해 사용한다. 디바이스 드라이버를 제거할때 구별자로도 사용된다. * 두값을 모두 비교해서 해제할 디바이스 드라이버를 선택한다.
문자 디바이스 드라이버의 등록과 해제 사용자 공간 커널 공간 드바이스 드라이버 module_init() { register_chrdev(); } struct file_operations { } module_exit() { unregister_chrdev(); } insmod 장치파일 응용프로그램 { open(); read(); write(); } rmmod chrdevs[MAX-]
#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);