I/O 서브시스템의 전체 적인 모습
위 서브시스템의 구조에 대해 살펴 보자
VFS 레이어에 파일 시스템과 디스크 캐시,
블록 레이어에 속한 I/O 스케줄러
디바이스 드라이버의 상호 작용이다
우선 파일에 데이터를 쓰는 경우, 파일에서 데이터를 읽는 경우를 나눠 생각 해 보자
-데이터를 쓰는 경우
파일 시스템의 파일에 데이터를 쓸 경우
1. 그 내용을 먼저 메모리의 디스크 캐시에 쓴다.
2. 데이터의 읽고 쓰기를 요청한 애플리케이션 프로그램(PS)은 이 단계에서 데이터를
읽거나 쓰는 동작을 맞쳤다고 생각하고 처리를 계속한다.
-디스크 캐시에 기록되어 있을 뿐 아직 물리 디스크에는 기록되지 않는 데이터가 생긴다
(이를 더티 데이터라 한다)
- 디스크 캐시에 더티데이터가 어느정도 쌓이게 되면 I/O 스케쥴러에게 물리 디스크에 기록요청
3. 이 요청을 I/O스케듈러 내부의 리퀘스트 큐에 추가되며 그에 따라 기록한다.
데이터 기록 빈도에 관련한 커널 파라미터들
vm.dirty_background_ratio
vm.dirty_ratio
-데이터 케시 데이터 비율을 vm.dirty_background_ratio %이하로 유지시킨다.
-더티 데이터의 비율이 vm.dirty_ratio % 를 넘으면 기록 빈도를 증가 시킨다.
vm.dirty_background_bytes
vm.dirty_bytes
-데이터 케시 데이터 비율을 vm.dirty_background_bytes "값" 이하로 유지시킨다.
-더티 데이터의 비율이 vm.dirty_bytes "값" 를 넘으면 기록 빈도를 증가 시킨다.
vm.dirty_writeback_centisecs : 값*(1/100)초 마다 디스크 캐시를 체크함
vm.dirty_expire_centisecs :값*(1/100)초 동안 기록 되지 않았던 내용 기록
-읽고 쓰기의 경우
상황1 : PS는 이 FS의 데이터를 읽는 경우,
1. 대상이 되는 데이터가 이미 디스크 캐시에 있는 경우
2. FS은 이 데이터를 SP에 반환하고 처리를 끝낸다.
상황2 : 대상이 되는 데이터가 이미 디스크 캐시에 있는 경우
1. 호출 한 PS는 일단 I/O를 기다리는 상태가 됨
2. 그 뒤에 파일 시스템은 I/O스케듈러에 데이터 읽기/쓰기 요청함
3. I/O 스케듈러가 요청에 응답하여 디스크 드라이브를 이용해 물리 디스크를 읽어온다
4. 이후 I/O대기를 해제 후 PS에 디스크 캐시의 데이터를 받아 전달함
I/O 스케줄러의 처리 방식
디스크 캐시와 물리디스크 사이에서 데이터 전송이 있을 경우
디스크 캐시 데이터의 배치와 물리 디스크 데이터 배치의 차이가 포인트다.
디스크 캐시에서 하나의 파일 데이터는 기본적으로 연속되는 메모리 영역을 갖지만
물리 디스크에서는 해당 데이터가 반드시 연결된 영역을 차지 하는 것은 아니다 (디스크 단편화)
어떤 파일의 데이터를 디스크 위에 어떻게 배치할 것인지 정하는 것이 파일 시스템에 역할이다.
1. 먼저 '파일 시스템'은 전송 대상의 데이터를 '물리 디스크' 연속 영역에 모아 준 뒤
"bio 객체"를 커널 내부에 생성해서 이것을 스케줄러에 전달한다.
2. 즉 파일 시스템에선 bio객체를 2개를 받는 것 이며 이것을 하나로 만든
"리퀘스트 객체"를 생성한다
3. 이후 리퀘스트 객체들은 서브큐에 쌓여지며 디스패치 큐에 의해 물리디스크에 간다.
아래 그림 참조
리눅스에서는 크게 4개의 I/O 스케줄러가 있다
noop 스케줄러
- 서브 큐를 하나만 가지고 받은 bio 순서대로 리퀘스트 처리
cfq 스케줄러
- 받은 bio는 그것을 보낸 PS의 프로셋 ID를 키로 하는 해시에 의해 64개의 서브큐 분류
이 후 일정량의 리퀘스트를 처리해간다 각 PS에 대해 공평하게 처리하는 편
deadline 스케줄러
-"읽기 리퀘스트용 서브 큐"와 "쓰기 리퀘스트용 서브 큐"를 각각 가진다.
-받아온 bio는 대응하는 섹터의 위치에 대해 큐에 있는 기존 리퀘스트의 최적위치에 삽입된다
큐의 앞에 있는 리퀘스트에 새로운 bio가 삽입되면 큐의 뒤에 있는 리퀘스트가 처리 안될경우도있음
그래서 일정시간 처리 되지 않은 리퀘스트를 우선적으로 처리한다.
-데이터 접근의 패턴이 복잡한 환경에서 고성능의 외부 저장 장치를 사용하는경우 이쪽이 효율이 좋을 수 있다.
anficipatory 스케줄러 : 데드라인 스케줄러에 다음에 받을 bio를 예상하는 기능을 추가한것이다.
이를 관리하는 위치는
/sys/block/{디바이스명(예sda)}/queue/schedular에 기록 되어 있다.
그리고 I/O스케줄러를 lsblk -t에 기록하고 있다.
그리고 시스템 디폴트 I/O 스케줄러 변경하기 위해선
/boot/grub/grub.conf의 커널 가동옵션에 elevator="값"을 지정해준다.
여담으로 io의 우선순위를 올리기 위해서 ionice 커멘드를 활용한다
ionice -c [class] 커맨드
class에는 Real time은 1 과 Best effort 2, Idle 3을 갖는다
이중에서도 우선 순위를 정하려면 -n 커맨드를 추가해서 0~7 값을 부여해준다.
또한 -p를 통해도 이미 진행중인 ps에 대해서도 가능하다.