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