Hard Disk
하드디스크는 위 그림과 같이 여러 원판(플래터)이 겹겹이 쌓여있는 구조로 되어있다.
그리고 원판의 앞/뒷 면에 데이터를 저장할 수 있다.
이 원판이 쌓여있는 원통형 구조를 실린더라고 부른다.
플래터에서 데이터를 읽는 것은 헤드가 담당하며, 헤드는 디스크 arm 에 붙어있다.
디스크 암은 좌우로 움직이면서 트랙을 이동할 수 있다.
플래터 하나는 여러개의 동심원으로 구성되어 있으며, 각각의 동심원으로 이루어진 영역을 트랙이라고 부른다.
그리고 트랙은 중앙을 향하는 세로선에 의해 분할된 '섹터' 로 구성된다.
왼쪽 그림을 보면 하드디스크 안쪽은 트랙당 섹터가 16개 이고, 바깥쪽은 트랙당 섹터가 32개로 되어있다.
반지름의 길이가 달라지기 때문에 2가지 종류의 트랙으로 구성한 것이다.
오른쪽 그림은 운영체제가 이해하는 디스크의 구조이다.
오른쪽에서는 모든 트랙이 동등하게 24개 섹터로 구성되어 있으며, 총 섹터의 개수는 왼쪽과 오른쪽이 같다.
과거 IBM 에서는 디스크에 접근할 때는 실런더 넘버, 헤드 넘버, 트랙넘버 조합을 통해 접근했다.
그런데 이 방식을 사용할 때 실런더 넘버, 헤드 넘버, 트랙넘버의 개수의 상한이 정해져 있었고, 그에 따라 디스크 용량도 30GB 정도의 크기로 제한되었기 때문에 지금은 이 방식대신 logical address 를 사용하는 방식을 채택했다.
위 그림은 플로피 디스크와 하드디스크의 성능을 비교한 데이터이다.
먼저 플로피 디스크에서 성능만 간단하게 계산해보면 다음과 같이 계산할 수 있다.
실린더의 개수는 40개, (아마 실린더를 플래터의 의미로 쓴 것 같다)
실린더당 트랙 개수는 2개
트랙당 섹터 개수는 9개
따라서 디스크에 있는 총 섹터 개수는 40 * 2 * 9 = 720
섹터당 용량이 512Byte 일 때, 디스크의 총 용량은 720 * 512 byte = 360KB
RAID
디스크에 데이터를 안전하게 저장하는 방법으로, Redundant Array of Independent Disks 의 줄임말이다.
여러 디스크를 사용하여 데이터를 저장할 때, 디스크의 성능과 안정성을 모두 높일 수 있는 저장 기법이다.
이 개념은 SLED (Single Large Expensive Disk, 하나의 큰 디스크에 모든 데이터를 저장하는 방법) 의 반대 개념이다.
RAID는 level 0 부터 level 5 까지 6개 단계에 걸쳐 데이터를 저장하는 방법을 단계 별로 나눈다.
Level 0
4개 디스크에 데이터를 분산해서 저장하는 방법
이때 데이터는 strip 단위로 쪼개서 저장한다.
하나의 strip은 k개의 섹터로 구성되어 있다. (k는 1도, 2도, 3도 될 수 있다.)
이렇게 저장하면, 대용량의 데이터를 3개 스트립에 나눠서 저장했을 때,
각 스트립이 3개 디스크에 분산되어 저장되어 있으므로 동시에 읽을 수 있어서 빠르게 읽고 쓰기를 할 수 있다는 장점이 생긴다.
예를 들어 1개 스트립이 1개 섹터로 구성될 때, 4개 섹터에서 데이터를 읽어야 한다면, RAID 가 아닌 방식에서는 1개 디스크에서 4개 섹터를 읽어야 하므로 시퀀셜하게 트랙이 돌면서 1개 섹터씩 데이터를 읽어야 한다.
반면 RAID 에서는 4개 디스크에서 1개 섹터씩 데이터를 동시에 읽어들이므로 훨씬 빠르게 데이터를 읽을 수 있다.
Level 0는 작은 데이터를 읽을 때보다, 큰 데이터를 읽을 때 이점을 갖는다.
또한 데이터를 중복해서 저장하지는 않기 때문에 redundancy는 없다.
하지만 장점만 있지는 않다.
먼저 디스크는 평균적으로 2만 시간에 한번씩 충돌이 발생한다고 한다.
그런데 이렇게 디스크를 4개를 사용해서 저장하면 평균적으로 5천 시간에 한번씩 충돌이 발생하는 셈이다.
따라서 reliablity는 SLED보다 오히려 좋지 않다. (이건 redundancy 가 없으면 어쩔 수 없이 발생하는 숙명이다)
Level 1
레벨 1은 똑같이 4개의 디스크를 추가해서 레벨 0 데이터를 그대로 복제해서 백업하는 방식을 말한다.
(그래서 '미러' 라고도 표현한다.)
이 방법은 redundancy가 존재하며, level 0 대비 읽기 성능을 최대 2배까지 끌어올릴 수 있다.
만약 8개 스트립 데이터를 읽어야 한다면, level 0 에서는 4개에서 동시에 읽고, 또 4개에서 동시에 한번 더 읽어야 했지만, level 1 에서는 8개 스트립을 한번에 동시에 읽을 수 있기 때문이다.
물론 작은 데이터에 대한 읽기 성능은 level 0때와 마찬가지로 크게 증가하지 않는다.
또한 level 1 은 Fault-tolerence 가 좋다.
그래서 한 드라이브에서 크래시가 발생하는 경우, 복제된 데이터로부터 데이터를 읽을 수 있으므로 level 0과 달리 reliability도 함께 챙길 수 있다.
(물론 좋기만 한 것은 아니다. level 0과 동일한 복제본을 유지하기 위한 비용이 평소에 계속 발생하기 때문이다.)
Level 2
level1까지는 스트립 단위로 데이터를 저장했다면, level2는 비트 단위로 쪼개서 데이터를 저장한다.
이때 (1byte = 8bit) 4비트 크기인 nibble을 3, 5, 6, 7 드라이브에 저장한다.
1, 2, 4 드라이브에는 parity 비트를 저장한다.
패리티 비트는 '해밍 코드'로 생성한다.
패리티 비트를 생성할 때는 크게 even parity 와 odd parity 방식이 있다.
예시로는 다음과 같이 생성한다.
먼저 3, 5, 6, 7 에 실제 데이터 비트를 저장한다.
첫 번째 비트(P1)는 1, 3, 5, 7 비트를 보고 P1을 결정한다.
이때 만약 even parity 를 사용한다면 1이 짝수개 되어야 하고, odd parity 를 사용한다면 1이 홀수개가 되어야 한다.
even parity를 사용하는 경우, 3 5 7 비트에 1이 총 짝수 개 존재하므로 P1은 0을 저장하면 된다.
두 번째 비트(P2)는 2, 3, 6, 7 비트를 보고 P2를 결정한다.
even parity를 사용하는 경우, 3, 6, 7 비트에 1이 홀수개 존재하므로 P2 = 1 이 되어야 한다.
네 번째 비트(P3)는 4, 5, 6, 7 비트를 보고 P3를 결정한다.
even parity를 사용하는 경우, 5, 6, 7 비트에 1이 짝수개 존재하므로 P3 = 0 이 되어야 한다.
그리고 이렇게 세팅한 7개 비트는 7개 하드디스크에 '동시에' 저장을 해야한다. (그래야 퍼포먼스가 좋다)
따라서 모든 하드디스크의 헤드가 동기화되어있다.
이렇게 패리티 비트를 사용하는 경우, 1bit 에러를 발견하고 고칠 수 있다는 장점이 있다.
만약 7번째 비트에 에러가 발생해서 비트가 반전되어 저장되었다면, P1 ~ P3 을 보고 모두 even parity 를 만족하는지 확인해서 만족하지 않으면 에러가 발생했음을 확인하고 에러를 고치는 것이다.
(위에서는 예시로 7번째 비트라고 했지만, 어떤 비트에서 에러가 발생했는지 P1~P3을 보면 특정할 수 있다.)
level 2에서는 크게 2가지 부담이 존재한다.
1. 모든 디스크의 헤드를 동기화하는 부담
2. 디스크 컨트롤러가 데이터를 읽은 뒤, 체크섬을 통해 에러를 확인하는 부담
대신 비트 에러가 발생했을 때 이를 검출하고 고칠 수 있다는 큰 장점이 있다.
Level 3
level 3 에서는 4개 비트 (nibble) 당 1개의 패러티 비트만 검사하는 방법으로 level 2보다 부담이 줄어든다.
level 3의 특징은 1bit 에러가 발생했을 때 이를 에러가 발생했다는 사실을 확인하는데 강하다.
(어디서 에러가 발생했는지는 알 수 없다.)
다만 디스크에서 크래시가 발생했을 때, 제한적으로 1bit 에러를 고칠 수 있다.
(크래시가 발생했을 때, even parity 인지 odd parity 인지에 따라서 1의 개수를 세어 크래시가 발생한 위치의 비트를 고칠 수 있다.)
다만 이 단계도 level 2와 마찬가지로 모든 비트가 한번에 데이터가 쓰여야 하므로 헤드를 동기화하는 부담이 존재한다.
Level 4
level 4는 다시 스트립 단위로 데이터를 저장한다.
이때 마지막 디스크에는 parity strip을 저장한다.
예를 들어 1스트립에 1섹터가 들어있고, (보통 1섹터는 512byte를 저장한다고 생각하지만 줄여서) 1 섹터에는 4bit 가 저장된다고 가정해보자.
그리고 Strip 0부터 3까지 각각
1010
0001
1100
1110
라고 하면 각 자리에 대해 exclusive or을 계산한다.
그러면 1이 짝수개 일 때는 0, 홀수개 일 때는 1이 나오므로 1001 이 나오며
이 값을 strip parity 로서 저장한다.
만약 특정 strip에서 에러가 발생하면, exclusive or 연산 결과를 토대로 strip을 복구할 수 있다.
level 4는 2, 3 과 다르게 디스크 헤드를 엄밀하게 동기화할 필요가 없어 부담이 적다.
대신 작은 변경사항이 발생했을 때, 모든 디스크를 다시 읽어서 다시 exclusive or 을 계산해야 하므로,
small update 에 대한 오버헤드가 크다는 부담이 있다.
또한 항상 값을 읽을 때마다 오류 검사를 위해 parity drive를 로드해야 하는 부담이 존재한다.
그래서 이 부담을 줄이기 위해 level 5 가 등장하였다.
Level 5
Level 5는 간단하다.
하나의 드라이브에만 페러티 스트립을 저장하다보니 해당 드라이브를 항상 로딩해야 하는 부담이 존재하니
여러 드라이브에 패러티 스트립을 분산해서 저장하자는 아이디어를 제시했다.
(그런데 어차피 4개 스트립을 읽을 때 나머지 하나도 로드해야 하는 건 똑같지 않나..싶다)
'CS > 운영체제' 카테고리의 다른 글
[운영체제] 23. Disk Format & Arm Scheduling (2) | 2024.12.10 |
---|---|
[운영체제] 21. I/O Device (0) | 2024.12.09 |
[운영체제] 20. UNIX V7 File System (0) | 2024.12.08 |
[운영체제] 19. 파일 시스템 구현 (0) | 2024.12.08 |
[운영체제] 18. File & Directory (0) | 2024.12.07 |