1. 초기화와 종료 처리디바이스
1.1 드라이버가 동작하기 위한 초기화/종료에 필요한 처리 항목(대표적)
1.2 디바이스 드라이버의 초기화/종료 처리 시점
1.3 모듈 초기화와 종료
3. I/O 영역의 경쟁 처리 함수
3.1 I/O 포트 영역의 경쟁 처리 함수
3.2 I/O 메모리 영역의 경쟁 처리 함수
* 디바이스 드라이버 초기화와 종료 함수 정리
1.1 드라이버가 동작하기 위한 초기화/종료에 필요한 처리 항목(대표적)
- 디바이스 드라이버의 등록과 해제
- 디바이스 드라이버에 내부 구조체의 메모리 할당과 해제
- 여러 프로세스가 하나의 디바이스에 접근할 때 필요한 사전 처리 및 종료 시 처리
- 주 번호에 종속된 부 번호를 관리하기 위한 사전 처리 및 종료 시 처리
- 하드웨어 검출 처리 및 에러 처리
- 하드웨어 초기화와 제거 가능한 하드웨어의 제거 처리
- 응용 프로그램에서 디바이스 드라이버를 사용하는 경우의 초기 처리 및 사용 종료 처리
- 부 번호에 관련된 프로세스별 처리
- 프로세스별 메모리 할당과 해제
- 사용하는 모듈 수의 관리
1.2 디바이스 드라이버의 초기화/종료 처리 시점
- 모듈 적재와 커널 부팅 처리 과징 / 제거 과정
- insmod 명령 : module_init : 모듈 적재과정
- rmmod 명령 : module_exit : 모듈 제거 과정 - 응용프로그램이 디바이스 파일을 여는 과정과 닫는 과정
- open() 함수 : file_operations.open : 디바이스 파일을 여는 과정
- close() 함수 : file_operations.release : 디바이스 파일을 닫는 과정
1.3 모듈 초기화와 종료
1.3.1 module_init의 초기화 처리
1.3.2 module_exit의 종료 처리
※ 실제로 디바이스 드라비어가 사용되는 시점 : 응용프로그램에서 open()함수로 열었을때 부터
1.3.3 open()함수 호출시 초기화 처리
1.3.4 release()함수 호출시 종료 처리
2. 모듈 사용 횟수 관리- 디바이스 드라이버의 등록
- 디바이스 드라이버에 내부 구조체의 메모리 할당
- 여러 프로세스가 하나의 디바이스에 접근하는 경우에 필요한 사전 처리
- 주 번호에 종속된 부 번호를 관리하기 위한 사전 처리
- 하드웨어 검출 처리 및 에러 처리
- 하드웨어 초기화
1.3.2 module_exit의 종료 처리
- 디바이스 드라이버의 해제
- 디바이스 드라이버에 할당된 모든 메모리의 해제
less(처리순서 예)..
(예) 처리순서
init()
{
// 하드웨어 검출 처리 및 에러 처리
// 하드웨어 초기화
// 디바이스 드라이버의 등록
// 디바이스 드라이버의 동작에 필요한 내부 구조체의 메모리 할당
// 여러 프로세스가 디바이스 하나에 접근하는 경우에 필요한 사전 처리
// 주 번호에 종속된 부 번호를 관리하기 위한 사전 천리
}
exit(){
// 디바이스 드라이버에 할당된 모든 메모리 해제
// 디바이스 드라이버의 해제
// 하드웨어 제거에 따른 처리
}
init()
{
// 하드웨어 검출 처리 및 에러 처리
// 하드웨어 초기화
// 디바이스 드라이버의 등록
// 디바이스 드라이버의 동작에 필요한 내부 구조체의 메모리 할당
// 여러 프로세스가 디바이스 하나에 접근하는 경우에 필요한 사전 처리
// 주 번호에 종속된 부 번호를 관리하기 위한 사전 천리
}
exit(){
// 디바이스 드라이버에 할당된 모든 메모리 해제
// 디바이스 드라이버의 해제
// 하드웨어 제거에 따른 처리
}
less(처리순서 예)..
※ 실제로 디바이스 드라비어가 사용되는 시점 : 응용프로그램에서 open()함수로 열었을때 부터
1.3.3 open()함수 호출시 초기화 처리
- 디바이스 드라이버가 처음 열렸을 때 하드웨어 초기화
- 디바이스 드라이버의 동작에 필요한 에러 체크
- 부 번호에 대한 처리가 필요한 경우 파일 오퍼레이션 구조체를 갱신
- 프로세스별 메모리 할당과 초기화
- 모듈의 사용 횟수 증가(kernel 2.4)
1.3.4 release()함수 호출시 종료 처리
- 프로세스별 할당 메모리 해제
- 모듈 사용 횟수 감소(kernel 2.4)
less..
커널 2.4에서는 디바이스 드라이버의 사용 횟수를 커널에서 관리하지 않고, 디바이스 드라이버 자체에서 처리하도록 하고 있음
less..
디바이스 드라이버가 모듈 형태라면 커널에 추가하거나 삭제하는 행위가 발생.
프로세스가 드라이버를 사용하는 도중에 디바이스 드라이버 모듈을 커널에서 제거하면 커널 자체에 문제가 생기므로 커널을 디바이스 드라이버의 사용 횟수를 감시하고, 사용하지 않을 때만 삭제할 수 있게 해야한다.
커널 2.4 : 디바이스 드라이버에서 사용 횟수 관리
커널 2.6 : 커널에서 사용 횟수 관리
프로세스가 드라이버를 사용하는 도중에 디바이스 드라이버 모듈을 커널에서 제거하면 커널 자체에 문제가 생기므로 커널을 디바이스 드라이버의 사용 횟수를 감시하고, 사용하지 않을 때만 삭제할 수 있게 해야한다.
커널 2.4 : 디바이스 드라이버에서 사용 횟수 관리
/linux/modules.h
release()함수 : MOD_DEC_USE_COUNT 매크로를 이용하여 모듈 사용횟수 감소
- MOD_INC_USE_COUNT : 모듈 사용 횟수를 증가시킨다.
- MOD_DEC_USE_COUNT : 모듈 사용 횟수를 감소시킨다.
- MOD_IN_USE : 모듈 사용 횟수가 0이 아니면 참값을 반환한다.
less..
int xxx_open(struct inode * inode, struct file * flip)
{
MOD_INC_USE_COUNT;
return 0;
}
{
MOD_INC_USE_COUNT;
return 0;
}
less..
release()함수 : MOD_DEC_USE_COUNT 매크로를 이용하여 모듈 사용횟수 감소
less..
int xxx_release(struct inode * inode, struct file * flip)
{
MOD_DEC_USE_COUNT;
return 0;
}
{
MOD_DEC_USE_COUNT;
return 0;
}
less..
커널 2.6 : 커널에서 사용 횟수 관리
핫 플러그인 처리가 필요한 경우처럼 디바이스 드라이버의 사용횟수를 직접 관리해야할 경우에
사용하는 함수
release()함수 : module)put() 함수를 이용하여 모듈 사용횟수 감소
사용하는 함수
- try_module_get(THIS_MODULE);: 모듈의 사용 횟수를 증가시킨다.
less..
반환값이 0이면 열기 실패 : 디바이스 드라이버 모듈이 적재되어 있지 않은 상태
※ 다른 프로세스가 커널에서 모듈을 제거하는 도중에 open()함수가 호출된 상태
(선점형 커널의 특성 때문에 발생하는 상황)
less..
- module_put(THIS_MODULE);: 모듈의 사용 횟수를 감소시킨다.
less..
int xxx_open(struct inode * inode, struct file * flip)
{
if(!try_module_get(THIS_MODULE)) return -ENODEV;
return 0;
}
{
if(!try_module_get(THIS_MODULE)) return -ENODEV;
return 0;
}
less..
release()함수 : module)put() 함수를 이용하여 모듈 사용횟수 감소
less..
int xxx_release(struct inode * inode, struct file * flip)
{
module_put(THIS_MODULE);
return 0;
}
{
module_put(THIS_MODULE);
return 0;
}
less..
3. I/O 영역의 경쟁 처리 함수
3.1 I/O 포트 영역의 경쟁 처리 함수
#include <linux/ioport.h>
자원의 충돌을 해결하기 위해 함수 사용 순서
- check_region : 등록할수 있는 I/O 영역인지 확인한다.
int check_region(unsigned long from, unsigned long extent); - request_region : I/O 영역을 등록한다.
void request_region(unsigned long from, unsigned long extend, const char * name);
※ request_region 등록시 지정하는 문자열은 디바이스 드라이버의 이름을 사용
cat /proc/ioports
- release_region : 등록된 I/O 영역을 해제한다.
void release_region(unsigned long from, unsigned long extent);
자원의 충돌을 해결하기 위해 함수 사용 순서
- 디바이스 드라이버 초기화 루틴에서 check_region() 함수를 사용해 해당 I/O영역의 사용 여부를 확인
- 해당 영역을 사용하지 않고 있다면 request_region() 함수를 사용해 점유 영역을 새로 등록
- 디바이스 드라이버를 제거 할 때는 release_region() 함수를 사용해 등록된 영역을 제거
less..
※ I/O메모리 포트 0x3FF0400번지부터 0x3FF040F까지의 영역을 사용하는 하드웨어의 예
int xxx_open(struct inode *inode, struct file *filp){
int err;
if(err = check_region(0x400), 0x10)) return err;
request_region(0x400, 0x10, "TEST");
return 0;
}
int xxx_release(struct inode *inode, struct file * filp)
{
release_region(0x400, 0x10);
....
return 0;
}
int xxx_open(struct inode *inode, struct file *filp){
int err;
if(err = check_region(0x400), 0x10)) return err;
request_region(0x400, 0x10, "TEST");
return 0;
}
int xxx_release(struct inode *inode, struct file * filp)
{
release_region(0x400, 0x10);
....
return 0;
}
less..
3.2 I/O 메모리 영역의 경쟁 처리 함수
#include <linux/ioport.h>
- check_mem_region : 등록된 자원인가를 확인한다.
int check_mem_region(unsigned long from, unsigned long extent);
- request_mem_region() : 자원을 등록한다.
void request_mem_region(unsigned long from, unsigned long extent, const char * name);
- release_mem_region() : 등록된 자원을 제거한다.
void release_mem_reion(unsigned long from, unsinged long extent);
less..
int xxx_open(struct inode *inode, struct file *filp){
int err;
if(err = check_mem_region(0x3FF0400), 0x10)) return err;
request_mem_region(0x3FF0400, 0x10, "TEST");
return 0;
}
int xxx_release(struct inode *inode, struct file * filp)
{
release_mem_region(0x3FF0400, 0x10);
....
return 0;
}
int err;
if(err = check_mem_region(0x3FF0400), 0x10)) return err;
request_mem_region(0x3FF0400, 0x10, "TEST");
return 0;
}
int xxx_release(struct inode *inode, struct file * filp)
{
release_mem_region(0x3FF0400, 0x10);
....
return 0;
}
less..
* 디바이스 드라이버 초기화와 종료 함수 정리