Search

Mass-Storage Systems

메모리 종류

위의 그림은 컴퓨터에서 사용되는 메모리들
오른쪽으로 갈수록 가격은 싸지고 용량은 커지지만 속도는 느려진다

레지스터

가장 빠른 기억장소, CPU 내에 존재
CPU가 사용하는 메모리로 굉장히 빠름
컴퓨터가 전원이 꺼지면 데이터가 사라지기 때문에 휘발성 메모리라고 부름
CPU를 구분할 때 32비트, 64비트 → 레지스터의 크기
32비트 레지스터 → 32bit CPU
CPU는 계산을 할 때 메인메모리에 있는 값을 레지스터로 가져와 계산을 한다.
계산 결과는 다시 메인메모리에 저장시킨다
왼쪽 : 명령어 오른쪽: 데이터
어셈블리 코드를 보는 이유
기계어로 일대일 매칭이 되기 때문에 실제로 레지스터를 사용하는 것을 볼 수 있기 때문
정확히 무슨 일을 하는지는 알 수 없지만 레지스터를 가지고 무언가 처리를 한다.

캐시

휘발성 메모리
레지스터와 메인메모리 사이 존재
메인메모리는 너무나 느리고 레지스터는 엄청 빠르다
메인 메모리에 있는 값을 레지스터로 옮기려면 한참 걸리기 때문에 미리 가져온다
미리 가져온 데이터를 저장하는 곳이 바로 캐시
캐시는 성능의 이유로 여러 개를 둔다
CPU가 값을 요청해 레지스터로 값을 옮겨야 한다면 단계에 따라 가장 속도가 빠른 L1 캐시를 보고 여기에 없다면 L2캐시를 확인해보고 여기도 없다면 메인 메모리에서 값을 가져온다

메인 메모리

프로그램이 실제로 올라갈 메인 메모리
실제 운영체제와 다른 프로세스들이 올라가는 공간
전원이 공급되지 않으면 데이터가 지워지기 때문에 휘발성 메모리
하드디스크나 SSD보다 속도는 빠르지만 가격이 비싸기 때문에 데이터를 저장하기 보다는 실행 중인 프로그램만 올린다
컴퓨터 시스템 자원 중 가장 중요한 것은 CPU이다. CPU 자원 관리에 대해서는 맨 처음 부분에서 다루었으며 CPU 스케줄링, 프로세스 동기화 등에 대해서 배웠다.
CPU 다음으로 중요한 자원은 메인 메모리와 같은 주기억장치이다. 메인 메모리 관리에 대한 주요 이슈는 페이징, 가상 메모리(요구 페이징) 등이 있었다.
CPU, 주기억장치 다음 중요한 컴퓨터 시스템 자원은 하드디스크와 같은 보조기억장치이다. 하드디스크가 데이터를 관리하는 방식은 파일 시스템이다. 파일은 컴퓨터에서 운영체제를 사용해본 사용자라면 매우 익숙한 단어일 것이다. 대표적인 windows 운영체제를 보면 폴더(디렉토리) 내부에 또 다른 폴더 또는 어떠한 파일이 존재한다. 이러한 폴더 및 파일은 트리 구조로 관리할 수 있다.

보조기억장치(하드디스크, SSD)

이전에 살펴본 메모리들은 휘발성 메모리에 가격이 비싸서 오래 저장할 파일을 저장하기 어려웠다.
가격이 저렴하고 전원이 공급되지 않아도 데이터가 지워지지 않는 비휘발성 메모리를 만들었다.
캐시와 레지스터와 같은 메모리로는 큰 용량을 만들려면 비용이 너무 크다.

하드디스크(HDD)

하드디스크
자기적으로 기록하여 저장할 수 있는 플래터, 암 등으로 이루어진 디스크
디스크는 대량의 보조 저장장치를 제공
위 그림은 하드디스크의 구조이다.
platter
실제 데이터를 기록하는 자성을 가진 원판. platter는 그림과 같이 여러 개가 존재하고 앞뒤로 사용할 수 있다. 한 platter는 여러 개의 track으로 이루어져 있다.
track
platter의 동심원을 이루는 하나의 영역.
sector
하나의 track을 여러 개로 나눈 영역을 sector. sector size는 일반적으로 512 bytes이며 주로 여러 개를 묶어서 사용.
cylinder
한 cylinder는 모든 platter에서 같은 track 위치의 집합을 말한다.
블록(block) : sector는 여러 개로 묶어서 사용되기 때문에 블록이라고도 불림 block device : 하드디스크는 블록 단위로 읽고 쓰기 때문에 block device 라고 불리기도 한다.
하드디스크가 블록 단위로 읽고 쓰는 것을 확인할 수 있는 간단한 방법은 메모장 프로그램에서 알파벳 a만을 적고 저장해보자.
a는 character로 1byte 크기를 갖는데, 실제 저장된 텍스트 파일의 속성을 확인하면 디스크에 4KB(하나의 block size)가 할당되는 것을 확인할 수 있다.(실제 디스크 할당 크기는 운영체제마다 다르다.)
참고 (free block을 어떻게 할당할까)

NVM(Nonvolatile Memory Device, 비휘발성 메모리)

디스크 고장
Disk write 도중에 전원이 나가면 consistency 가 깨짐.
버퍼는 휘발성이라 cpu는 버퍼에 쓴 순간 디스크에 썼다고 생각하지만 고장으로 인해 디스크에 써지지 못한 상황 → 비휘발성 버퍼(journaling file system)을 추가
SSD, 자기테이프
SSD (Solid State Disk)
하드 디스크처럼 사용되는 비휘발성 메모리
기계적 이동 부품이 없어 신뢰도 ↑ 탐색, 지연이 없어 속도↑, 전력소모↓
자기테이프
초기의 보조 저장장치 매체. 현재는 백업용, 장기저장용으로 사용
NVM (Nonvolatile Memory Device)란?
NVM
SSD 나 USB 드라이브가 NVM 의 일환
seek time 이 일정하기에 FCFS 스케쥴링을 사용함
이동 디스크 헤더가 없으므로 간단한 FCFS를 수행한다. (FIFO)
Merging 기법 : 요청 중 비슷한 공간에 있는 애들을 합쳐서 한 번에 요청
DWPD(Drive Writes Per Day) : 제품에 명시된 보증기간을 사용하기 위한 하루 권장 write 회수
NAND Flash Controller Algorithms
FTL (Flash Translation Layer) 를 통해 유효한 데이터를 가지는 valid logical block 을 추적
삭제는 페이지 단위로는 불가능하고, 블럭 단위로만 가능하며 덮어쓰기 또한 물리적으로 불가능함
따라서 덮어쓰기를 하려면 valid page 를 미리 옮겨두고, 원래 블럭을 지운 뒤 덮어쓰기 하고자 하는 페이지와 백업해둔 페이지를 다시 쓰는 귀찮은 작업이 필요함 :
위 방법으로 invalid page 를 청산하는 것을 garbage collection 이라함
garbage collection 을 위해서는 valid page를 옮겨둘 수 있는 free block 이 필요한데 모든 블럭이 사용중이라면 이것이 불가능하니 오버 프로비저닝(Over-provisioning) 기법을 사용함
오버 프로비저닝(Overprovisioning) : 전체 사용량의 80%만 사용자에게 공개하고, 나머지는 free block 으로 사용하는 기법

디스크 스케쥴링 알고리즘

디스크에 접근하는 시간은 Seek time(탐색 시간) + rotational delay + transfer time 으로 계산할 수 있는데, 이 중에서 seek time(head를 움직이는 시간)이 가장 크다.
탐색 시간 : 어떤 device의 arm이 head를 움직이는데 특정 cylinder의 특정 sector를 찾는 것
대역폭을 최대화한다.
대역폭 : 전송된 총 바이트 수 / 첫 서비스 요청 시간 - 마지막 전송 완료 시간 (완료시간 - 요청시간)
현재 컴퓨터 환경은 대부분 다중 프로그래밍 환경이다. 그러므로 여러 프로세스가 메인 메모리에서 실행 중에 있는데, 이러한 여러 프로세스가 동시에 디스크를 읽으려는 요청이 올 수 있다. 이와 같은 요청이 오면 디스크 역시 CPU와 같이 디스크 큐(disk queue)에서 요청을 저장해두고 이를 처리해야 한다.
여기서 컴퓨터의 성능을 위해 여러 요청들을 효율적으로 처리해야 한다.
디스크를 읽는 시간은 매우 오래 걸리는 작업이고 특히 탐색 시간이 오래걸리므로 최대한 이 시간을 줄이는 것이 중요하다.
이러한 방법들을 디스크 스케줄링 알고리즘이라 한다.

FCFS(First-Come First-Served)

이 방법은 어느 스케줄링 알고리즘에서도 존재하는 가장 간단하고 가장 공평한 방법이다. 바로 예제를 살펴보자.
들어온 순서대로 헤드를 움직인다
200 cylinder dist: 0, 1, 2, ..., 199 Disk queue: 98, 183, 37, 122, 14, 124, 65, 67 현재 헤드가 가리키는 실린더(cylinder) 위치: 53
Plain Text
복사
예제를 그림으로 나타내면 위 그림과 같다. 가로축은 0번부터 199번까지 실린더의 위치를 나타낸다. 여기서 파란색 선이 disk queue를 FCFS 방법으로 처리한 결과이다.
헤드가 움직인 총 거리
= (98 - 53) + (183 - 98) + (183 - 37) + (122 - 37) + (122 - 14) + (124 - 14) + (124 - 65) + (67 - 65) = 640 cylinders
위 그림의 결과를 본 것처럼 큐에 들어온 순서가 큰 값, 작은 값이 반복한다면 헤드가 움직이는 거리가 매우 커짐을 알 수 있다.

SSTF(Shortest-Seek-Time-First)

SSTF 스케줄링 알고리즘은 가장 짧은 탐색 시간을 먼저 선택하는 것이다. 다시 말하면 현재 헤드가 다음 요청을 처리하기 위해 움직여야 하는 거리가 가장 짧은 것을 선택하는 것이다.
200 cylinder dist: 0, 1, 2, ..., 199 Disk queue: 98, 183, 37, 122, 14, 124, 65, 67 현재 헤드가 가리키는 실린더(cylinder) 위치: 53
Plain Text
복사
처음 헤드 위치 53을 시작으로 dist queue에 있는 실린더 번호 중 53과 가장 가까운 65번 실린더를 선택한다. 65번에서는 가장 가까운 67번을 선택하고 같은 과정을 반복한다.
헤드가 움직인 총 거리
= (65 - 53) + (67 - 65) + (67 - 37) + (37 - 14) + (98 - 14) + (122 - 98) + (124 - 122) + (183 - 124) = 236 cylinders
SSTF 스케줄링 알고리즘의 결과는 위 예제에서 FCFS 스케줄링보다 훨씬 적은 수의 실린더를 움직이는 것을 볼 수 있다. 하지만 SSTF 스케줄링의 큰 단점은 기아(starvation)가 발생할 수 있다.
disk queue에는 지속적으로 새로운 프로세스의 요청이 들어오기 때문에 헤드와 멀리 떨어져 있는 실린더는 끝내 수행하지 못하는 현상이 발생하는데, 이를 starvation이라고 한다.
SSTF 스케줄링이 현재와 가장 가까운 실린더를 선택한다고 해서 최적의 알고리즘은 아니다. 
위 예제에서도 가장 처음 위치인 53번 실린더에서 65번이 아닌 37번으로 이동한 후에 SSTF 알고리즘을 수행하면 208 cylinders 가 나온다.(그리디가 아니다)

Scan

Scan 스케줄링은 말그대로 헤드가 지속적으로 디스크를 앞뒤로 검사하는 것이다.
그래서 헤드가 앞으로 스캔할 때(번호가 작은 실린더 방향)와 뒤로 스캔할 때(번호가 큰 실린더 방향) 선택하는 실린더가 서로 다르다.  관성을 고려하여 한방향으로 쭉 가다가 끝이면 반대 방향으로 돈다.
200 cylinder dist: 0, 1, 2, ..., 199 Disk queue: 98, 183, 37, 122, 14, 124, 65, 67 현재 헤드가 가리키는 실린더(cylinder) 위치: 53 스캔 방향: 0번 방향으로 움직임(번호가 작은 실린더 방향)
Plain Text
복사
위 결과에서 볼 수 있듯이 스캔 방향이 0번 실린더 방향이므로 53번에서 작은 번호의 실린더로 향한 후에 큰 번호 실린더로 움직인 것을 볼 수 있다.
헤드가 움직인 총 거리
= (53 - 37) + (37 - 14) + (14 - 0) + (65 - 0) + (67 - 65) + (98 - 67) + (122 - 98) + (124 - 122) + (183 - 124) = 236 cylinders

C-Scan

여기서 한 가지 생각해 볼 점은 일반적으로 프로세스들이 디스크에 요청할 때 그 위치를 종합해보면 실린더에 골고루 퍼져있다.
그러므로 Scan 스케줄링 알고리즘처럼 앞뒤로 움직이는 것이 아니라 처음부터 한 방향으로 끝까지 움직이고 다시 처음으로 되돌아가서 같은 방향으로 끝까지 움직이는 것이 더욱 효과적이다.
이러한 아이디어에서 나온 것이 Circular Scan 스케줄링 알고리즘이다.
Circular Scan 스케줄링 알고리즘
한 방향으로 계속 움직이는 것.
Scan 방식은 끝에 다다랐을 때 반대방향으로 가는데, 굳이 그럴 필요가 없다.
물론 오른쪽에서 왼쪽 끝으로 갈 때 한바퀴를 돌기 때문에 움직이는 거리는 더 길어질 수 있지만 다시 처음 위치로 되돌아갈 때는 데이터를 읽지 않으므로 더 빠른 속도로 움직일 수 있다. (그냥 모터로 슝 긁으면 된다.)

Elevator Algorithm

Elevator Algorithm은 Scan과 파생되어 나온 알고리즘(C-scan, scan)을 부르는 다른 용어이다.
위 Scan 스케줄링 알고리즘 예제 그림을 90도로 회전하면 엘리베이터의 모습과 유사하여 붙여진 이름이다.

볼륨과 파티션

하드웨어 저장장치는 볼륨을 담고있는 파티션으로 구분됨
각 볼륨은 파일 시스템으로 정형화됨

파티션

파티션 : 볼륨을 논리적으로 나눈 것
파티션은 특정 파일 시스템으로 포맷하거나 raw 한 상태로 둘 수도 있음. raw 상태는 swap space 로 사용됨

Boot Block

컴퓨터 부팅
초기 부트스트랩 로더는 NVM 플래시 메모리에 펌웨어로 저장됩니다.
메모리의 주소는 하드웨어에 의해 설정됩니다.
시스템의 모든 부분을 초기화하고 스토리지에서 부트스트랩 프로그램 로드
부트 디스크의 부트 블록에 저장된 부트스트랩 프로그램
부트 스트랩 프로그램 : OS 를 로딩하는 프로그램
Windows: MBR (Master Boot Record)
부트 디스크 또는 시스템 디스크 : 부트 파티션이 있는 장치
OS 커널 로드
부팅 순서
1.
부트 로더 실행
a.
ROM 에 부트로더가 다 들어가 있으면 그냥 부트로더가 바로 실행됨
b.
부트로더가 용량이 커서 다 들어가지 못하면 부트로더를 실행시키는 부트 스트래퍼(Boot strapper)가 실행
2.
부트로더가 부트 코드를 실행
3.
부트 파티션의 OS 가 로딩되어 실행
a.
Boot partition: contains OS kernel + device drivers

Storage Attachment(디스크 부착 설계)

어느 상황에서 어떤 디스크 부착을 검토할지 설계
DAS(Direct Attached Storage)
서버에 직접 연결하는 방식
NAS(Network Attached Storage)
네트워크를 통해서 서버와 스토리지를 연결
서버와 저장장치가 이더넷 등의 LAN 방식의 네트워크에 연결된 방식
LAN은 TCP/IP 프로토콜 기반, 저장장치는 SCSI 사용 ⇒ 통신을 위해 중계역할의 파일서버 필요
확장성, 유연성이 뛰어남
경제적, 설치 쉬움
커넥션 증가 시 성능문제 발생 가능성
미들웨어 구조로 보는 NAS(Network Attached Storage) 활용 예시
SAN(Storage Area Network)
SAN 스위치를 구성한 뒤 서버와 스토리지를 연결
성능↑, 확장성 ↑
서버와 저장장치를 광섬유 스위치로 연결한 고속 데이터 네트워크
SAN 스위치를 구성한 뒤 서버와 스토리지를 연결
확장성, 유연성, 가용성 우수
DAS, NAS, SAN 비교

RAID

데이터 보호를 위한 별의별 아이디어

RAID 개념

RAID(Redundant Array of Inexpensive Disks)
오늘 날 필요성의 대두
반드시 백업이 필요한 경우
스토리지에 물리적인 이상이 발생하더라도 사용자가 체감할 수 없어야 함
용량 증설 검토 시 데이터의 손실 없이 증설 필요
여러 개의 디스크를 배치하여 속도↑, 안정성 ↑, 효율성 ↑, 가용성 ↑
하드 디스크를 여러 개 배치하여 쓰는 것
신뢰성(Reliability) 좋음
하나가 고장나도 다른 디스크를 통해 작업을 이어가는 것
MTTF(Mean Time To Failure) or MTBF(Mean Time Between Failure) : 고장과 고장 사이의 평균 시간
Mean Time to Repair : 고장을 고치는데 걸리는 평균 시간
Mean Time to Data Loss = MTTF / M * MTTF / MTTR : 모든 디스크가 고장나서 데이터를 수용할 수 없는 주기
M = 디스크의 수
사실 하드디스크의 주된 고장 원인이 갑작스런 전원 차단인데 보통 하나가 끊기면 다 같이 끊겨서 다 같이 고장나기 때문에 MTDL 이 더 낮음
크게 미러링(mirroring), 스트라이핑(striping)으로 나눠짐
Mirroring : 디스크 내용을 복제해두어 사고 발생해도 정상 동작하도록 함
Striping : 디스크를 병렬로 두어 데이터를 여러 디스크에서 동시에 읽어들임 ⇒ 성능 (Performance) 좋음
RAID Level
RAID 0 (Stripe)
두 개 이상의 디스크에 데이터를 무작위로 write
장점: 데이터 사용시 I/O를 디스크 개수만큼 분할하여 쓰기 때문에 I/O 속도가 향상됨
단점: 디스크 중 하나의 디스크라도 장애가 발생하면 복구가 어려움
RAID 1 (Mirror)
디스크에 동일한 데이터를 중복 기록. 적어도 동일한 디스크 두 개가 필요
장점: 디스크 두 개가 한번에 오류가 발생하지 않는 이상 가용성이 높고, 복구가 쉬움
단점: 사용할 수 있는 디스크가 실제 디스크의 절반
RAID 2 (Stripe)
에러 체크, 수정을 위한 해밍코드 사용. ECC(Error Correction Code)를 별도의 드라이브에 저장
단점: ECC가 저장된 드라이브 손상의 경우 복구가 어려움 (현재는 거의 사용되지 않음. deprecated)
RAID 3,4 (Stripe)
에러 체크 및 수정을 위해 패리티 정보를 별도의 디스크에 저장
RAID 3은 데이터를 바이트 단위로 나누어 분산, RAID4는 블록단위로 나눔
장점: 성능 보완. 디스크 용량을 온전히 사용할 수 있음
단점: 별도의 패리티 디스크의 손상 시 리스크 존재
RAID 5 (Stripe)
패리티 정보 자체를 stripe로 구성된 디스크 내에서 처리하게 만듬
장점: 하나의 디스크가 손상되더라도 남은 디스크들로 데이터 복구가 가능
RAID 6 (Stripe)
기본적인 개념은 RAID5와 동일. 2차 패리티 정보를 넣어 2개의 디스크에 문제가 생겨도 복구가 가능
장점: 안정성이 굉장히 높음
단점: 약간의 데이터 공간 사용이 추가적으로 발생
RAID 0 + 1 : 먼저 병렬하게 디스크를 구성한 뒤 디스크들을 복제
RAID 1 + 0 : 디스크를 먼저 복제한 뒤 각각이 병렬로 디스크를 재구성