[OS] 하드디스크 드라이브

장선규·2023년 10월 9일
1

[OS] OSTEP Study

목록 보기
25/28

하드디스크 드라이브

이 장에서는 하드디스크 드라이브에 대해서 자세히 살펴볼 것이다.

핵심 질문 : 디스크에 있는 데이터를 어떻게 저장하고 접근하는가

  • 현대 하드 디스크 드라이브는 어떻게 데이터를 저장하는가?
  • 인터페이스는 무엇인가?
  • 데이터는 실제로 어떻게 배치되고 접근되는가?
  • 디스크 스케줄링은 어떻게 성능을 개선시킬 수 있는가?

1. 인터페이스

현대 디스크 드라이브의 인터페이스를 이해하는 것부터 시작해 보자.

드라이브 인터페이스

  • 드라이브는 읽고 쓸 수 있는 매우 많은 수의 섹터(512 byte 블럭)들로 이루어져 있다.
  • 디스크 위의 n개의 섹터들은 0부터 n-1까지의 이름이 붙어있고, 때문에 디스크를 섹터들의 배열로 볼 수 있다.
    • 0부터 n-1이 드라이브의 주소 공간이 된다.
  • 멀티 섹터 작업도 가능하다.
    • 많은 파일 시스템들이 한 번에 4KB를 읽거나 쓴다.
    • 하지만 드라이브 제조사는 하나의 512byte 쓰기만 원자적이라고 보장한다.
    • 찢긴 쓰기(torn write): 갑작스러운 전력 손실 등의 이유로 대량의 쓰기 중에 일부만 완료되는 현상
  • 디스크 드라이브의 "계약 불문율"
    • 가정1) 드라이브의 주소 공간에서 가깝게 배치되어 있는 두 개의 블럭을 접근하는 것은 멀리 떨어져 있는 두 개의 블럭을 접근하는 것보다 빠르다.
    • 가정2) 연속적인 청크의 블럭을 접근하는 것이 가장 빠르며, 랜덤 접근 패턴보다 매우 빠르다.

2. 기본 구조

현대 디스크의 주요 요소

  • 플래터(platter): 데이터의 기록 공간으로, 표면에 있는 자기적 성질을 변형하여 데이터를 지속시킨다.
    • 2개의 표면(surface)를 갖는다.
    • 드라이브 전원이 나가더라도 비트를 드라이브에 영구적으로 저장하기 위해 얇은 자성층이 입혀져 있다.
  • 회전축(spindle): 플래터의 중심을 고정하고, 플래터를 일정한 속도로 회전시키는 축이다.
    • 회전 속도는 분당 회전 수(RPM)으로 측정 (일반적으로 7,200~15,000 RPM)
    • ex) 10,000 RPM -> 한 바퀴 회전하는데 6ms 걸림
  • 트랙(track): 플래터의 각 표면에 동심원들 (동심원을 따라 섹터들이 배치되어 있다)
  • 디스크 헤드(disk head): 디스크의 자기적 패턴을 감지하거나 변형시켜 읽기와 쓰기 동작을 하는 기계 장치
    • 표면마다 하나씩 헤드 존재
  • 디스크 암(disk arm): 디스크 헤드를 원하는 트랙 위에 위치하도록 이동시키는 장치

3. 간단한 디스크 드라이브

디스크가 어떻게 동작하는지 이해하기 위해 그림과 같이 하나의 트랙으로만 이루어진 간단한 디스크를 생각해보자.

  • ex) 트랙이 하나만 존재하는 디스크
    • 이 트랙에는 12개의 섹터가 있고, 각 섹터는 512 byte의 크기를 갖는다.
    • 주소 영역은 0~11
    • 디스크 헤드는 섹터 6번에 위치
    • 표면은 시계 반대 방향으로 회전

단일 트랙 지연 시간: 회전 지연

만약 블럭 0번을 읽는다고 하면, 디스크가 이 요청을 어떻게 처리해야 할까?

  • 트랙이 하나 뿐이므로, 그냥 디스크 헤드 아래에 원하는 섹터가 위치하기를 기다리면 된다.
  • 이러한 기다림을 회전 지연(rotation delay)라고 부르고, I/O 서비스 시간에서 중요한 요소라고 한다.
    • 예제에서 만약 한 바퀴를 다 회전하는 데 걸리는 회전 지연이 R이라고 하자.
    • 디스크 헤드가 0에 위치하기 위해서는 R/2 이 필요하다.

멀티 트랙: 탐색 시간

현대 디스크들은 당연하겠지만 수백만 개의 트랙을 갖고 있다. 멀티 트랙 디스크를 이해하기 위해 세 개의 트랙만이 존재하는 디스크의 예제를 보자.

  • ex) 세 개의 트랙이 존재하는 디스크
    • 섹터: 바깥쪽 (0~11) / 중간 (12~23) / 안쪽 (24~35)
    • 만약 11번 섹터를 읽어야 한다면?
      • 디스크 암을 올바른 트랙 (바깥쪽) 위로 위치시켜야 한다. 이 과정을 탐색(seek)이라고 하고, 이는 비싼 디스크 동작이다.
      • 탐색(seek)
        1. 가속 단계: 디스크 암이 움직이기 시작
        2. 활주 단계: 디스크 암이 최고 속도로 움직임
        3. 감속 단계: 디스크 암의 속도가 줄어듦
        4. 안정화 단계: 정확한 트랙 위에 헤드가 조심스럽게 위치하게 됨
          (안정화 시간은 매우 중요하며 0.5~2ms 정도로 오래 걸린다.)
      • 탐색 과정에서 플래터가 당연히 회전한다. 이제 11번 섹터까지 회전 지연 후에 전송을 할 수 있다.
      • 섹터 11번에 헤드가 위치하면, I/O의 마지막 단계인 전송이 이루어져 표면 위의 데이터를 읽거나 쓴다.

그 외의 세부 사항

트랙 비틀림(track skew)

  • 트랙의 경계를 지나서 순차적으로 존재하는 섹터들을 올바르게 읽을 수 있게 하는 기술
  • 한 트랙에서 다른 트랙으로 전환하는 경우에 디스크의 헤드를 다시 위치시키기 위한 시간이 필요하다.
  • 이와 같은 비틀림이 없다면 헤드가 다음 트랙으로 넘어 갔을 때 다음에 읽어야 하는 블럭이 이미 헤드를 지나쳤을 수도 있다.
  • 때문에 다음 블럭을 접근하기 위해 거의 한 바퀴에 해당하는 회전 지연을 감수해야 한다.

멀티 구역(multi-zoned) 디스크 드라이브

  • 디스크 바깥 측에 공간이 더 많기 때문에, 바깥 측 트랙들에는 안쪽 트랙들보다 더 많은 섹터들을 갖고 있다.
  • 디스크들은 여러 구역으로 나뉘어 있으며 한 구역은 표면 위에 연속적으로 존재하는 트랙들의 집합이다.
  • 각 구역 내의 트랙은 같은 수의 섹터들을 포함하고 있으며 바깥 측 구역의 트랙에는 안쪽 구역의 트랙보다 많은 수의 섹터들을 갖고 있다.

캐시(cache) 혹은 트랙 버퍼(track buffer)

  • 캐시는 일반적으로 8 또는 16MB 정도의 작은 크기의 메모리로, 드라이브가 디스크에서 읽거나 쓴 데이터를 보관하는 데 사용한다.
    • ex) 디스크에서 하나의 섹터를 읽을 때 드라이브가 그 트랙 위의 모든 섹터를 다 읽어서 캐시에 저장할 수도 있다.
  • 쓰기의 경우 드라이브는 캐싱에 대한 두 가지 선택지가 있다.
    • write-back 캐싱: 메모리에 데이터가 기록된 시점에 쓰기가 완료되었다 판단
    • write-through 캐싱: 디스크에 실제로 기록되었을 때 완료되었다 판단

4. I/O 시간 계산

이제 추상화된 디스크 모델을 만들었으니 간단한 분석을 통해 디스크의 성능을 구할 수 있다.

세 개의 항으로 이루어진 다음의 식을 통해 I/O 시간을 나타낼 수가 있다.

  • I/O 시간에 대한 식
  • I/O 속도에 대한 식
    • 드라이브 간의 비교용

I/O 시간에 대한 이해를 돕기 위해 계산을 해 보자. 두 개의 워크로드가 있다고 가정하자.

  • 랜덤 워크로드 - 디스크에 4KB의 작은 읽기 요청 발생시킴
  • 순차 워크로드 - 헤드의 이동 없이 디스크에 연속되어 있는 여러 개의 섹터를 단순히 읽음
  • 디스크 드라이브 명세
    • 치타는 "성능" 위주의 드라이브로 속도가 빠르다.
    • 바라쿠다는 "용량" 위주의 드라이브로 느리지만 많은 비트를 저장한다.
    • 디스크 드라이브 성능
      • 랜덤 워크로드와 순차 워크로드 간의 성능 차이가 크다.
        (치타의 경우 거의 200배 이상 차이가 나고, 바라쿠다의 경우 300배 이상 차이가 난다.)
      • "성능" 위주의 드라이브와 "용량" 위주의 드라이브 간의 성능 차이가 크다.

5. 디스크 스케줄링

I/O의 비용이 크기 때문에 디스크 스케줄러가 요청을 조사하여 다음에 어떤 I/O를 처리할지 결정하는 것이 중요하다.

각 작업의 길이가 얼마나 될지 알 수 없는 작업 스케줄링과 다르게, 디스크 스케줄링의 경우, 디스크 요청 작업이 얼마나 길지를 꽤 정확히 예측할 수 있다.

  • 요청의 탐색과 회전 지연의 정도를 예측하면 각 요청이 얼마나 오래 걸릴지 디스크 스케줄러가 알 수 있다.
  • 때문에 (greedy 방식으로) 처리할 수 있는 가장 빠른 요청을 선택할 수 있다.
  • 디스크 스케줄러는 SJF(shortest job irst, 짧은 작업 우선) 의 원칙을 따르려고 노력한다.

SSTF: 최단 탐색 시간 우선

최단 탐색 시간 우선(Shortest-seek-time-irst,SSTF)

  • SSTF는 트랙을 기준으로 I/O 요청 큐를 정렬하여 가장 가까운 트랙의 요청이 우선 처리되도록 한다.
    • ex) 현재 헤드의 위치가 안쪽 트랙에 위치해 있다고 하자.
      • 가운데 있는 트랙의 섹터 21번과 바깥 측의 섹터 2번에 대한 요청을 받으면,
        21 -> 2번 순으로 처리
  • 문제점
    1. 드라이브의 구조는 호스트 운영체제에게 공개되어 있지 않으며 운영체제는 그저 블럭들의 배열로만 인식한다.
      • 가장 가까운 블럭 우선(Nearest-block-irst, NBF) 방식을 사용하면 된다.
      • 이 방식은 가장 가까운 블럭 주소에 접근하는 요청을 다음에 처리하도록 스케줄한다.
    2. 기아 현상(starvation)
      • 만약 위의 예제에서 현재 헤드가 위치하고 있는 안쪽 트랙에만 지속적으로 요청이 발생한다면?
      • 순수한 SSTF 방식에서는 다른 트랙에 있는 요청들은 완전히 무시될 것이다.

핵심 질문: 디스크 요청의 기아 현상을 어떻게 처리할까
SSTF와 유사한 스케줄링을 구현하면서 어떻게 기아 현상을 피할 수 있을까?

엘리베이터 (SCAN 또는 C-SCAN)

SCAN 방식

  • 트랙의 순서에 따라 디스크를 앞뒤로 가로지르며 요청을 서비스한다.
  • 디스크를 한 번 가로지르는 것을 (밖에서 안으로 또 안에서 밖으로) 스위프 (sweep) 라고 부르자.
  • 따라서 어떤 요청이 이번 스위프에 이미 지나간 트랙에 대해 들어온다면 바로 처리되지 않고 다음 번 스위프에(반대 방향) 처리되도록 큐에서 대기한다.

F-SCAN 방식

  • 스위프하는 동안에는 큐를 동결시키는 방식
  • 디스크를 스위프 하는 동안에 새로운 요청이 도착하면 다음 번 서비스 될 큐에 삽입한다.
  • 이와 같이 현재 요청과 가까이 있지만 늦게 도착한 요청들의 처리를 지연시켜 멀리 떨어져 있는 요청에 대한 기아 현상을 없앴다.

C-SCAN 방식

  • Circular SCAN의 약자이다.
  • 디스크를 한 방향으로 스위프하는 대신 이 알고리즘은 밖에서 안으로 그리고 다시 안에서 밖으로 스위프한다.

그러나 SCAN(또는 SSTF 까지도) 방식은 SJF의 원칙을 지키기 위해 최선을 다하지 않는다. 구체적으로는 이 기법들은 회전을 무시한다.

핵심 질문: 디스크 회전 비용을 고려하려면 어떻게 해야 할까
어떻게 하면 탐색과 회전을 모두 고려하여 SJF를 가장 근접하게 모방하는 알고리즘을 만들 수 있을까?

SPTF: 최단 위치 잡기 우선

최단 위치 잡기 우선(shortest positioning time first)

  • 위의 상황에서 8번으로 갈지 16번으로 갈지는 상황에 따라 다르다.
  • 상황에 의존적인 이유는 "탐색에 걸리는 시간"과 "회전에 걸리는 시간"이 다르기 때문이다.
    • 탐색시간 > 회전지연: SSTF나 그 변종 방식들이 잘 동작한다
    • 탐색시간 < 회전지연: 더 먼 탐색인 8번 요청을 먼저 처리하는 것이 유리
      (16번은 거의 한바퀴를 다 돌아야함)

다른 스케줄링 쟁점들

디스크 스케줄링은 현대 시스템에서 어느 부분이 담당해야 하는가?

  • 예전 시스템의 경우 운영체제가 모든 스케줄을 결정하였다.
  • 현대 시스템에서 디스크는 대기 중인 여러 개의 요청들을 수용할 수 있으며 복잡한 내부 스케줄러를 자체적으로 밖고 있다.
    • 이 스케줄러는 디스크 컨트롤러 내부에 있기 때문에 헤드의 정확한 위치도 알 수 있을 뿐만 아니라 그 외의 필요한 정보들도 알 수 있다.
    • 그래서 SPTF 방식을 정밀하게 구현할 수 있다.
    • 운영체제의 스케줄러는 최선의 요청을 모두 디스크에 내려보내고, 디스크는 상세한 트랙 배치 정보와 헤드의 위치에 대한 내부 지식을 사용하여 최선의 (SPTF) 순서로 정렬한다.

I/O 병합(I/O merging)

  • 만약 33번, 8번, 34번을 읽는 요청이 온다면?
    • 33,34번 요청을 병합하여 두 블럭 길이의 요청으로 만든다.
    • 병합된 요청을 반영하기 위해 스케줄러는 해당 요청들을 재배치한다.
    • 디스크로 내려보내는 요청의 개수를 줄이면 오버헤드를 줄일 수 있기 때문에 운영체제에서 병합은 특히 중요하다.

디스크로 I/O를 내려보내기 전에 시스템은 얼마나 기다려야 하는가?

  • 작업 보전(work-conserving) 방식: 단 하나의 I/O만 있더라도 디스크로 즉시 내려보내기
  • 작업 비보전(non-work-conserving) 방식: 잠시 기다렸다가 디스크로 내려보내기
profile
코딩연습

0개의 댓글