커널 2.6의 블록 디바이스 드라이버

Download Report

Transcript 커널 2.6의 블록 디바이스 드라이버

22. 블록 디바이스 드라이버
김진홍
[email protected]
2015.10.11.
목차
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
2/29
개요
• 블록 디바이스 드라이버
• 리눅스에서 지원하는 세가지 핵심 디바이스 드라이버 중 하나
• 문자
리눅스와 블록 디바이스
• 블록
하드 디스크의 특성
• 네트워크
블록 디바이스 드라이버와 요구 큐
• 하드디스크와 같은 저장 디바이스
• 블록단위의 입출력
• 일반적으로 마운트를 통해 파일시스템을 구현하는 시스템으로
사용 됨
• 요구 큐라는 request_queue_t 구조체를 이용해 입출력
• 2.4일때와 2.6일때가 전혀 다름 => 스케줄러의 향상
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
3/29
리눅스와 블록 디바이스
• 하드디스크와 디바이스 파일
• 윈도우의 표현 방법
• 하나의 파티션으로 구성됨
• C:, D:
• 물리적인 하드디스크를 표현하는 방법이 없음.
• 리눅스의 표현 방법
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
• 하나의 디바이스 파일로 취급
• /dev/hda
• /dev/hdb
• 디바이스 파일에 파티션을 분할
• /dev/hda1
• /dev/hda2
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
4/29
리눅스와 블록 디바이스
• 문자 드라이버와 차이점
VFS
리눅스와 블록 디바이스
하드 디스크의 특성
버퍼 처리
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
문자 디바이스 드라이버
블록 디바이스 드라이버
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
장치
request 방식의 가상 하드 디스크
5/29
하드 디스크의 특성
• 하드디스크의 데이터 처리 방식
• 하드디스크에 데이터를 읽거나 쓰기 위해 드라이버에 명령을 줌
• 인터럽트로 요구된 처리가 끝났는지 확인함
• 쓰기
리눅스와 블록 디바이스
하드 디스크의 특성
•
디스크 드라이버가 하드디스크에 쓰기 명령과 함께 쓸 데이터를 전달
•
커널에서 논리적인 섹터 번호와 써 넣을 데이터의 주소가 전달 됨
•
디바이스 드라이버가 실제 섹터 위치를 지정하는 값으로 변환
•
쓰기 완료 후 드라이버의 인터럽트 서비스 함수가 커널에 인터럽트를 발생 시킴
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
• 읽기
•
드라이버가 디스크에게 데이터 읽기 명령 전달
•
섹터 번호와 읽어올 데이터를 넣을 주소.
•
완료 후 인터럽트 발생
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
6/29
하드 디스크의 특성
• 하드디스크의 데이터 처리 방식
• 특정 섹터를 읽은 다음 다른 섹터를 읽으려면 최소한 한바퀴의 디스크 회전이 필요.
리눅스와 블록 디바이스
• 미리 읽기
• 읽을 섹터를 기준으로 여분의 섹터를 더 읽음
• 장점
• 이전에 읽은 데이터를 응용에서 요구하면 디스크 접근 없이 버퍼에서 바로
읽을 수 있음.
• 클러스터
• 섹터가 아닌 클러스터 단위로 처리하는 것
• e.g. 두개의 섹터를 하나의 클러스터 단위로 처리.
• 장점
• 미리 읽기시 여분의 읽기 섹터 수를 고정 처리하는 효과가 있음
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
7/29
블록 디바이스 드라이버와 요구 큐
• 호출 주체에 따른 입출력 처리
• 호출 주체에 따라 두 가지로 나뉨
1. 외부에서 블록 디바이스에 직접 접근
•
응용에서 디스크의 내용을 읽거나 쓸 수 있도록 드라이버에게 직접 요구
리눅스와 블록 디바이스
하드 디스크의 특성
-> 드라이버에서 수행
•
블록 디바이스 드라이버와 요구 큐
e.g.
•
fdisk 같은 파티션 분할 프로그램
2. 블록 디바이스를 응용 프로그램에서 간접 접근
1. 응용이 파일에 읽기/쓰기를 수행
2. 파일 시스템에서 드라이버에 읽기/쓰기 요청
3. 디바이스가 읽기/쓰기 수행
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
8/29
블록 디바이스 드라이버와 요구 큐
• 문자 드라이버와의 처리 방식의 차이점
• 문자 드라이버
• 응용에서 읽기를 시도하면 file_operation의 read() 함수에서 처리
• 블록 드라이버
• 응용 프로그램의 읽기에 대응하는 read()함수가 없음.
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
• 읽기 루틴 구현의 필요성
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
9/29
블록 디바이스 드라이버와 요구 큐
• 문자 드라이버와의 처리 방식의 차이점
• 블록 드라이버에서 읽기 요청
1. 응용 프로그램에서 read 요청
리눅스와 블록 디바이스
2. 커널이 커널 내부 버퍼에 있는지 살펴봄
하드 디스크의 특성
3. 있으면 전달, 없으면 드라이버에 요청
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
• 커널은 디바이스를 효율적으로 처리하기 위해 처리할 내용을 큐에 모아 둠
• 일정 시간이 지나거나 임계치에 도달하면 드라이버에 처리를 요구
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
• 커널과 드라이버간의 전달은 요구 큐와 처리 함수를 이용
• 문자 드라이버와 다른 점임.
request 방식의 가상 하드 디스크
10/29
버전별 블록 디바이스 처리
• 새로운 입출력 스케줄러
• 읽기 요청을 우선 처리
• 엔터프라이즈 환경에서 읽기가 더 발생
• 요구 큐의 데드라인 도입
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
11/29
버전별 블록 디바이스 처리
• bio 구조체
• 진행중인 블록 IO 연산에 대한 직관적인 인터페이스 제공
• 블록 IO 요청이 bio 구조체로 표시됨
• 요청에 있는 각 블록이 bio_vec 이라는 구조체에 저장되어 배열로 관리됨
• bio_vec은 <page, offset, len>과 같은 형식으로 표현 되면서 하나의 IO 연산을
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
나타냄.
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
12/29
커널 2.6의 블록 디바이스 드라이버
• 블록 디바이스 드라이버 작성 요구 사항
• 블록 디바이스의 특성 정의
• 주 번호와 부 번호 및 디바이스명에 대한 정의
리눅스와 블록 디바이스
• 블록 디바이스 드라이버 등록
하드 디스크의 특성
• 블록 디바이스 드라이버를 위한 구조체 선언
블록 디바이스 드라이버와 요구 큐
• 파일 오퍼레이션 구조체 처리
버전별 블록 디바이스 처리
• 요구 큐에 관련된 처리 및 함수 선언
• 블록 디바이스 추가를 위한 gendisk 구조체 생성 및 등록
• 블록 디바이스의 크기 설정 및 기타 속성 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
13/29
커널 2.6의 블록 디바이스 드라이버
• 블록 디바이스 드라이버 등록과 해제
• 등록
리눅스와 블록 디바이스
• 모듈 초기화 함수
• 커널에 의해 호출 되는 초기화 함수
하드 디스크의 특성
• register_blkdev()
블록 디바이스 드라이버와 요구 큐
• 인자 : 주번호, 디바이스 이름
버전별 블록 디바이스 처리
• 해제
• unregister_blkdev()
• 인자 : 주 번호, 디바이스 이름
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
14/29
커널 2.6의 블록 디바이스 드라이버
• 블록 디바이스 드라이버를 위한 구조체 선언
• 블록 디바이스 드라이버를 다루기 위한 내용
1.
request_queue 구조체 변수
•
2.
gendisk 구조체 변수
•
3.
블록 디바이스 처리를 위해
spinlock_t 구조체 변수
•
4.
요구 처리를 위해
request 방식을 사용할 경우 필요함
블록 디바이스를 위한 자체적인 정보 변수
typedef struct
{
void *priv; //자체 정보 관리 주소변수
struct request_queue *queue;
spinlock_t lock;
struct gendisk *gd;
} xxx_device;
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
15/29
커널 2.6의 블록 디바이스 드라이버
• struct block_device_operations
• 블록 디바이스가 동작하기 위해서는 위 구조체를 이용해 동작을 위한 기본
함수들을 등록 해야함.
리눅스와 블록 디바이스
• 이 구조체는 gendisk 구조체의 fops 필드에 등록 됨.
하드 디스크의 특성
• add_disk() 함수에 의해 gendisk 구조체가 등록될 때 함께 등록 됨.
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
16/29
커널 2.6의 블록 디바이스 드라이버
• struct block_device_operations
• 메소드
•
struct module *owner;
•
•
•
리눅스와 블록 디바이스
파일 오퍼레이션의 소유자
open/release
•
디바이스가 마운트/언마운트 될 때 호출 됨.
•
모듈 카운트 관리
ioctl
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
(struct inode *inode, struct file *filp, unsigned int cmd, unsigned log arg)
•
인자 cmd에 들어갈 항목
•
BLKGETSIZE – 섹터 수로 표현되는 블록 디바이스의 크기를 응용에 전달.
•
BLKFLSBUF – 드라이버 내부에 저장된 버퍼의 내용을 실제 디바이스에 모두 써 넣기
•
BLKRAGET – 응용에서 디바이스에 설정되어 있는 읽기 값을 미리 얻어 옴
•
BLKRASET – 디바이스의 미리 읽기 값을 설정
•
BLKRRPART – 디바이스의 파티션 테이블을 다시 읽기 요청함
•
HDIO_GETGEO – 디바이스의 특성을 디스크 구조에 대한 형태로 응용에 제공
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
17/29
커널 2.6의 블록 디바이스 드라이버
• struct block_device_operations
• 메소드
•
•
media_changed
•
CD-ROM 처럼 제거 할 수 있는 디바이스를 다루기 위해 주기적으로 호출해 검사 함.
•
이를 구현 하면 revalidate_disk를 필수로 선언해야 함
revalidate_disk
•
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
디바이스가 교체 되었다면 디바이스 상태를 재설정 해야함.
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
18/29
커널 2.6의 블록 디바이스 드라이버
• 요구 큐 관련 처리 및 함수
• make_request 방식
• 램디스크, loop
• request 방식
• 대부분의 경우
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
19/29
커널 2.6의 블록 디바이스 드라이버
• make_requst 방식
• bio 구조체를 사용 하여 처리
• 블록 디바이스에 읽기나 쓰기 발생
->커널이 make_request() 함수를 호출해 처리를 요구함
static int xxx_make_request(request_queue_t *q, struct bio *bio)
{
struct bio_vec *bvec;
• bio 구조체 중요 변수
: //요구 유효성 검사 처리
•
bio_for_each_segment(bvec, bio, i)
{
: // 요구 처리
}
bio_endio(bio, bio->bi_size, 0); // 처리 종료
return 0;
fail :bio_IO_error(bio, bio->bi_size);
return 0;
}
bio->bi_bdev->bd_disk->private_data
: 디바이스 관리를 위한 구조체 메모리 주소
•
bio_data_dir(bio): 처리 방향
•
bio->bi_sector : 논리적 시작 섹터 번호
•
bio->bi_size : 처리해야 할 총 데이터 크기
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
20/29
커널 2.6의 블록 디바이스 드라이버
• request 방식
• 대부분의 블록 디바이스의 경우 request를 이용하여 처리
• elv_next_request() 함수로 처리할 구조체가 없을때 종료
static void xxx_request(request_queue_t *q)
•
request 구조체 중요 변수
•
{
xxx_req -> rq_disk->private_data
: 디바이스를 관리하기 위해 할당한 메모리 주소
struct request *xxx_req
while(1)
•
xxx_req -> sector : 처리해야 할 논리적 섹터번호
{
•
xxx_req ->current_nr_sectors : 처리해야 하는 섹터 수
•
xxx_req -> buffer : 읽기나 쓰기를 처리할 데이터의 선두 주소
xxx_req = elv_next_request(q);
if(!xxx_req) return ;
: //처리 루틴
•
기타 처리 함수
•
get_capacity(xxx_req -> rq_disk)
if(처리 성공) end_request(xxx_req, 1);
•
처리중인 디바이스의 용량을 구함.
else
•
request 함수 초기에 처리 요구 범위가 디바이스의 크기를
end_request(xxx_req, 0);
넘는지 검사
}
}
•
rq_data_dir(xxx_req)
•
처리 방향을 얻음
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
21/29
커널 2.6의 블록 디바이스 드라이버
• gendisk 구조체 생성 및 등록
• 커널 2.6에서 드라이버가 디바이스를 처리하기 위해서는 add_disk() 함수를
이용해 등록
•
for(lp =0; lp<XXX_MAX_DEVICE; lp++)
리눅스와 블록 디바이스
하드 디스크의 특성
{
device[lp].gd = alloc_disk(XXX_MAX_PARTITIONS);
블록 디바이스 드라이버와 요구 큐
device[lp].gd->major = XXX_DEV_MAJOR;
device[lp].gd->fops = &vhdd_fops;
버전별 블록 디바이스 처리
device[lp].gd->queue = device[lp].queue;
device[lp].gd->private_data = &device[lp];
커널 2.6의 블록 디바이스 드라이버
sprintf(device[lp].gd->disk_name, “vhdd%c”. ‘a’+lp);
set_capacity(device[lp].gd, XXX_SECTOR_TOTAL);
make_request 방식의 램디스크
add_disk(device[lp].gd);
}
• add_disk는 gendisk 구조체 변수를 이용해 디바이스의 정보를 커널에 등록
request 방식의 가상 하드 디스크
22/29
커널 2.6의 블록 디바이스 드라이버
• gendisk 구조체 생성 및 등록
• gendisk 구조체를 이용해 디바이스를 등록하고 제거할 때 사용하는 함수
• alloc_disk : gendisk 구조체 생성
• add_disk : 등록
• del_gendisk : 제거
• put_disk : 구조체 소멸
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
23/29
커널 2.6의 블록 디바이스 드라이버
• gendisk 구조체 생성 및 등록
• add_disk 이용전 gendisk 구조체 할당과 필드 설정 필요
•
#include <linux/genhd.h>에 선언 되어 있음
• alloc_disk() 함수에서 초기화 됨
리눅스와 블록 디바이스
하드 디스크의 특성
• 드라이버가 추가적으로 초기화 해야 하는 필드
•
int major ::주번호
•
int first_minor ::부 번호
•
struct block_device_operations *fops:: 블록 파일 오퍼레이션 구조체 변수 주소
•
struct request_queue *queue :: 디바이스 요구 처리를 위한 변수 주소
•
char disk_name[16] :: 디바이스 이름
•
•
int flags :: 디바이스의 특성
•
•
/proc/partition에 나타남
cd-rom 이나 removable 디바이스
void *private_data :: 정보 처리를 위한 변수 주소 (request() 함수에서 구할 수 있음)
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
24/29
커널 2.6의 블록 디바이스 드라이버
• gendisk 구조체 할당과 해제
• gendisk 구조체 변수를 할당하고 해제
리눅스와 블록 디바이스
• 할당
• struct gendisk *alloc_disk(int minors)
• 해제
• void put_disk(struct gendisk *disk)
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
25/29
커널 2.6의 블록 디바이스 드라이버
• gendisk 구조체 등록과 해제
• gendisk 구조체를 커널에 등록하고 해제
리눅스와 블록 디바이스
• 등록
• void add_disk(struct gendisk *disk)
• 해제
• void del_gendisk(struct gendisk *gp)
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
26/29
커널 2.6의 블록 디바이스 드라이버
• 블록 디바이스의 크기 설정
• 커널에 등록하기 전 디바이스의 크기를 설정 해야 함
• void set_capacity(struct gendisk *disk, sector_t size)
리눅스와 블록 디바이스
하드 디스크의 특성
블록 디바이스 드라이버와 요구 큐
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
27/29
커널 2.6의 블록 디바이스 드라이버
• 블록 디바이스 제거
• 대부분의 블록 디바이스 드라이버는 커널이 부팅 될 때 등록 됨
• 만약 드라이버 모듈을 제거할 때는 다음 순서를 거쳐야 함
리눅스와 블록 디바이스
1.
del_gendisk()를 이용하여 제거
하드 디스크의 특성
2.
alloc_disk()로 할당한 메모리를 put_disk()로 해제
블록 디바이스 드라이버와 요구 큐
3.
등록된 요구 큐를 blk_cleanup_queue()로 커널에서 제거
4.
등록된 디바이스를 unregister_blkdev()를 이용해 제거
버전별 블록 디바이스 처리
커널 2.6의 블록 디바이스 드라이버
make_request 방식의 램디스크
request 방식의 가상 하드 디스크
28/29
Qna
29/29