'운영체제: 아주 쉬운 세 가지 이야기' 책이 배송되기 전에 큰 그림을 잡기 위해 빠르게 훑어보려 도서관에서 빌려왔다.
'컴퓨터 구조 및 설계' 를 읽고나서 보니 겹치는 영역이 많아서 읽기 편하다.
아래의 내용은 '쉽게 배우는 운영체제' 책의 내용을 정리한 것이다.
[Chapter 1. 운영체제의 개요]
운영체제: 사용자에게 편리한 인터페이스 환경을 제공하고 컴퓨터 시스템의 자원을 효율적으로 관리하는 소프트웨어
운영체제의 역할
- 자원 관리 (효율성)
- 자원 보호 (안정성)
- 하드웨어 인터페이스 제공 (확장성)
- 사용자 인터페이스 제공 (편리성)
그리드 컴퓨팅: 분산 시스템의 한 분야.
운영체제의 구조
커널: 프로세스 관리, 메모리 관리 등 운영체제의 핵심적인 기능을 모아놓은 것
인터페이스: 커널에 서용자의 명령을 전달하고 실행 결과를 사용자에게 알려주는 역할
시스템 호출(system call): 커널이 자신을 보호하기 위해 만든 인터페이스. 커널이 제공하는 시스템 자원의 사용과 연관된 함수이다.
응용 프로그램이 하드웨어 자원에 접근하거나 운영체제가 제공하는 서비스를 이용하려 할 때는 sys-call을 사용해야 한다.
커널이 하는 일
- 프로세스 관리
- 메모리 관리
- 파일 시스템 관리
- 입출력 관리
- 프로세스 간 통신 관리
단일형 구조 커널
커널의 핵심 기능을 구현하는 모듈들이 하나로 구성되어 있다.
계층형 구조 커널
비슷한 기능을 가진 모듈을 묶어서 하나의 계층으로 만들고 계층 간의 통신을 통해 운영체제를 구현하는 방식이다.
마이크로 구조 커널
기본적인 기능만 제공한다. 하나의 모듈이 실패하더라도 전체 운영체제가 멈추지 않는다.
[Chapter 2. 컴퓨터의 구조와 성능 향상]
폰노이만 구조: 모든 장치가 버스로 연결되어 있는 구조. 모든 프로그램은 메모리에 올라와야 실행할 수 있다.
CPU: 산술논리 연산장치, 제어장치, 레지스터로 구성됨
레지스터의 종류: DR, AR, PC, IR, MAR, MBR 등
버스는 CPU, 메모리, 주변장치 간에 데이터를 주고 받을 때 사용한다.
버스의 종류에는 제어 버스, 주소 버스, 데이터 버스가 있다.
버스의 대역폭은 한번에 전달할 수 있는 대역폭의 최대 크기를 말한다.
부팅: 운영체제를 메모리에 올리는 과정
버퍼: 속도에 차이가 있는 두 장치 사이에서 그 차이를 완화하는 역할
스풀: 버퍼와 비슷한 개념이지만 프로그램 간에 배타적이다
캐시: 메모리와 CPU간의 속도 차이를 완화하기 위한 장치
캐시의 변경된 데이터를 메모리에 반영하는 방법에는 즉시 쓰기(write-through)와 나중 쓰기(write-back)가 있다
인터럽트: 입출력 관리자가 CPU에게 보내는 작업 완료 신호. 신호를 받으면 CPU는 하던 일을 멈추고 옮겨진 데이터를 처리해야 한다. (컴퓨터 구조에서 봤던 내용이랑 조금 상이한것 같아서 확인이 필요)
직접 메모리 접근(DMA)
인터럽트 방식의 시스템을 구성하는 데 필수 요소이다.
메모리 매핑 입출력: DMA를 위한 공간을 분리하여 메모리의 일정 공간을 입출력에 할당하는 것.
사이클 훔치기: CPU와 DMA가 메모리에 동시에 접근시 DMA에게 메모리 사용 권한을 양보하는 것.
병렬 처리
여러개의 스레드를 동시에 처리하는 것을 멀티스레드라고 하며 파이프라인과 슈퍼스칼라가 있다.
병렬 처리시 고려 사항
- 상호 의존성이 없어야 병렬 처리가 가능하다
- 각 단계의 시간을 거의 일정하게 맞춰야 병렬 처리가 원만하게 이루어진다
- 전체 작업 시간을 몇 단계로 나눌지 잘 따져보아야 한다
병렬 처리 기법
파이프라인: 명령어를 겹쳐서 실행하는 방법으로 하나의 프로세서에 여러개의 스레드를 실행하는 것
데이터 해저드, 구조적 해저드, 제어 해저드가 발생할 수 있다.
데이터 해저드는 전방전달(load-use data hazard의 경우 버블을 통해서만 해결할 수 있다), 구조적 해저드는 메모리를 두개로 나누어서, 제어 해저드는 지연과 예측 두가지로 해소할 수 있다. 특히 제어 해저드는 완전한 해결 방법이 없다.
슈퍼스칼라: 파이프라인이 처리할 수 있는 프로세서를 여러개 구성하여 여러개의 명령어가 동시에 실행되는 것. 대부분 슈퍼스칼라를 이용한다.
슈퍼파이프라인, 슈퍼파이프라인 슈퍼스칼라, VLIW(S/W적으로 병렬처리)기법도 있다
무어의 법칙: 반도체의 트랜지스터 집적도가 2년마다 2배씩 증가한다는 이론. 최근에는 정체되면서 잘 맞지 않게 되었다.
암달의 법칙: 컴퓨터 시스템의 일부를 개선할 때 전체적으로 얼마만큼의 최대 성능 향상이 있는지 계산하는데 사용한다.
[Chapter 3. 프로세스와 스레드]
프로그램과 프로세스: 프로그램은 저장장치에 저장되어있는 정적인 상태, 프로세스는 메모리에 올라온 동적인 상태.
프로그램을 메모리에 올릴때 운영체제 영역에 프로세스 제어 블록(PCB)를 생성한다.
간단한 프로세스의 네 가지 상태
- 생성 상태: 프로세스 제어 블록(PCB) 생성
- 준비 상태: CPU를 얻을 때 까지 기다리는 상태
- 실행 상태: 작업을 수행. 시간내에 완료하지 못했다면 준비 상태로 돌아간다.
- 완료 상태: PCB가 사라진 상태
입출력이 추가되면 준비와 실행 사이에 대기 상태가 추가된다. 이 다섯가지를 활성 상태라고 한다.
PCB의 구성
- 포인터: PCB를 연결하여 큐를 구현할 때 사용
- 프로세스 상태
- PID
- PC
- 프로그램 우선순위
- 각종 레지스터 정보
- 메모리 관리 정보
- 할당된 자원 정보
- 계정 정보
- PPID, CPID
문맥 교환(context switching): 기존의 프로세스가 나가고 새로운 프로세스를 받아들이는 작업
프로세스의 연산
프로세스의 구조
- 코드 영역: 프로그래머가 작성한 코드가 탑재되는 영역. 읽기 전용으로 처리된다.
- 데이터 영역: 코드가 실행되면서 사용하는 변수나 파일 등의 각정 데이터를 모아놓은 곳.
- 스택 영역
프로세스의 생성과 복사
복사: fork() sys-call을 통해 복사한다. 프로세스의 생성 속도가 빠르고 추가 작업 없이 자원을 상속할 수 있다.
exec() sys-call시 프로세스는 그대로 둔 채 내용만 바꾼다. 이미 만들어진 프로세스의 구조를 재활용하는 것이다.
프로세스의 계층 구조는 동시에 여러 작업을 처리하고 종료된 프로세스의 자원을 회수하는 데 유용하다.
부모 프로세스는 자원을 회수하기 위해 자식 프로세스가 끝날 때까지 기다려야 하지만 부모 프로세스가 먼저 종료되거나 자식 프로세스가 비정상 적으로 종료될 시 프로세스가 비정상적으로 남게 되는데 이를 미아 프로세스(orphan process) 또는 좀비 프로세스(zombie process)라고 한다.
스레드
프로세스의 코드에 정의된 절차에 따라 CPU에 작업 요청을 하는 실행 단위이다.
프로세스는 여러개의 스레드로 구성되어 있다.
서로 독립적인 프로세스는 데이터를 주고받을 때 프로세스 간 통신(IPC)을 이용한다.
멀티스레드: 프로세스 내의 작업을 여러개의 스레드로 분할
멀티태스킹: 하나의 프로세서가 여러개의 스레드를 시분할 시스템으로 작업
멀티프로세싱: 슈퍼스칼라와 같다
CPU 멀티스레드: H/W적인 방법으로 하나의 프로세서에서 여러 스레드를 동시에 처리하는 병렬 처리 기법
프로세스 복사시 멀티태스킹은 정적인 영역까지 모두 복사하기 때문에 중복되는 영역이 많아져서 자원의 낭비가 있다. 하지만 멀티스레드는 정적인 영역은 공유하면서 동적인 영역만 따로 관리하기 때문에 자원을 아껴서 효율적이다.
멀티스레드의 장점
- 응답성 향상: 한 스레드가 입출력으로 인해 작업이 진행되지 않더라도 다른 스레드가 작업을 계속하여 사용자의 작업 요구에 빨리 응답할 수 있다.
- 자원 공유: 모든 스레드가 자원을 공유하게 되어 작업을 원활하게 진행할 수 있다.
- 효율성 향상: 불필요한 자원의 중복을 막아서 시스템의 효율의 향상된다.
- 다중 CPU 지원
멀티스레드의 단점
하나의 스레드에서 문제 발생시 프로세스 전체에 영향을 미친다.
멀티스레드 모델
커널 스레드: 커널이 직접 관리하는 스레드
사용자 스레드: 라이브러리에 의해 구현된 일반적인 스레드. 커널 스레드를 사용하려면 sys-call로 사용해야 한다.
- 사용자 레벨 스레드: OS가 멀티스레드를 지원하지 않을 때 사용하는 방식
- 커널 레벨 스레드: 커널이 멀티스레드를 지원하는 방식. 사용자 레벨 스레드와 장단점이 반대이다.
- 멀티 레벨 스레드: 위의 두개를 혼합한 방식.
프로세스의 영역
정적 할당 영역: 코드, 데이터
동적 할당 영역: 스택, 힙
- 스택: 함수 호출과 복귀시, 지역변수에 사용. 스레드가 작동하는 동안 추가되거나 삭제되는 동적 할당 영역.
- 힙: 동적으로 할당되는 변수 영역.
wait() sys-call을 통해 부모-자식 프로세스 간의 동기화를 맞춰줄 수 있다.
[Chapter 4. CPU 스케줄링]
고수준 스케줄링: 시스템 내의 전체 작업 수를 조절한다(멀티프로그래밍 정도). 고수준 스케일링에 따라 시스템에서 동시에 실행 가능한 프로세스의 총 개수가 정해진다.
저수준 스케줄링: 고수준의 반대이다. 프로세스의 상태를 변경한다. 실제로 작업이 이루어지는 단계이다.
중간 수준 스케줄링: 고수준과 저수준 사이에서 중지와 활성화를 통해 프로세스 수를 조절하여 과부하를 막는다. 프로세스의 보류 상태에 해당한다. 저수준 스케줄링이 원만하게 이루어지는 buffer 역할을 한다.
고수준->중간수준->저수준 순으로 이루어진다.
스케줄링의 목적
- 공평성: 모든 프로세스가 자원을 공평하게 배정받아야 한다
- 효율성: 시스템 자원이 유휴 시간 없이 사용되도록 해야한다
- 안정성: 우선순위를 통해 중요 프로세스가 먼저 작동하게 하고 나쁜 프로세스로부터 자원을 보호해야 한다
- 확장성: 프로세스가 증가해도 시스템이 안정적으로 작동하도록 조치해야 한다
- 반응 시간 보장: 시스템은 적절한 시간 안에 프로세스의 요구에 반응해야 한다
- 무한 연기 방지: 특정 프로세스의 작업이 무한히 연기되어서는 안된다
하지만 안정성과 효율성을 높이기 위해 일정 부분 공평성을 희생한다.
선점형 스케줄링: 운영체제가 프로세서를 강제로 빼앗을 수 있다. (예: 인터럽트) 대부분의 저수준 스케줄러에서 사용한다.
비선점형 스케줄링: 다른 프로세스가 프로세서를 빼앗을 수 없다
CPU 집중 프로세스: CPU 버스트가 많은 프로세스
I/O 집중 프로세스: I/O 버스트가 많은 프로세스
두 개가 같이 있을 때는 I/O 집중 프로세스를 먼저 실행 상태로 옮기는 것이 효율적이다.
전면 프로세스: GUI 운영체제에서 화면의 맨 앞에 놓인 프로세스. 상호작용 프로세스라고도 한다.
후면 프로세스: 사용자와 상호작용이 없는 프로세스. 일괄 작업 프로세스라고도 한다.
(우선순위 높음) <-> (우선순위 낮음)
커널 프로세스 일반 프로세스
전면 프로세스 후면 프로세스
I/O 집중 프로세스 CPU 집중 프로세스
다중 큐
프로세스의 우선순위를 배정하는 방식
- 고정 우선순위: 프로세스가 끝날때 까지 우선순위가 바뀌지 않는다. 구현은 쉽지만 시스템의 변화에 대응하기 어렵다.
- 변동 우선순위: 프로세스 작업 도중에 우선순위가 변한다. 구현이 어렵다.
반전 우선순위를 통해 시스템의 효율성을 향상시킬 수 있다.
대기 상태에서도 다중 큐를 사용한다.
준비 상태의 다중 큐는 한번에 하나의 프로세스를 꺼내서 프로세서를 할당하는 반면, 대기 큐는 여러개의 PCB를 동시에 꺼내서 준비 상태로 옮긴다. 여기서 인터럽트 벡터라는 자료 구조를 사용한다.
스케줄링 알고리즘
스케줄링 알고리즘의 효율성을 파악하는 평가 기준은 다음과 같다.
- CPU 사용률
- 처리량
- 대기 시간
- 응답 시간
- 반환 시간
스케줄링 알고리즘의 성능을 비교할 때는 주로 평균 대기 시간을 본다.
비선점형 알고리즘
- FCFS 스케줄링: 준비 큐에 도착한 순서대로 프로세서를 할당하는 비선점형 방식. FIFO 스케줄링 이라고도 한다.
- SJF 스케줄링: 준비 큐에 있는 프로세스 중에 실행시간이 가장 짧은 작업부터 프로세서를 할당한다. 하지만 운영체제가 프로세스의 종료 시간을 정확하게 예측하기 어렵고 공평성을 위배하는 문제가 있다. 만약 실행시간이 짧은 작업이 계속해서 들어와 특정 작업이 계속 연기된다면 기아(starvation) 현상이 발생해서 잘 사용하지 않는다.
- HRN 스케줄링: SJF에서 발생할 수 있는 기아 현상을 해결하기 위해 만들어졌다. 하지만 공평성은 여전히 위배될 수 있다.
선점형 알고리즘
- 라운드 로빈 스케줄링: 할당받은 시간 동안 작업을 하고 완료하지 못하면 준비 큐의 맨 뒤로 가서 차례를 기다리는 방식이다. FCFS 스케줄링과 유사하다. 문맥 교환 시간이 추가되어 실제 평균 대기시간은 더 길어진다.
- SRT 스케줄링: SJF+라운드 로빈 스케줄링을 혼합한 방식이다. 남은 시간이 적은 프로세스에 프로세서를 먼저 할당한다. SJF 스케줄링과 마찬가지로 종료 시간을 예측하기 어렵고 기아 현상이 일어나기 때문에 잘 사용하지 않는다.
- 다단계 큐 스케줄링: 우선순위에 따라 준비 큐를 여러개 사용한다. 큐는 라운드 로빈 방식으로 운영된다. 우선순위가 높은 상위 큐 프로세스의 작업이 끝나기 전까지 하위 큐 프로세스의 작업을 할 수 없다.
- 다단계 피드백 큐 스케줄링: 다단계 큐 스케줄링의 문제점을 보완한 방식이다. 프로세서를 사용하고 난 프로세스의 우선순위가 낮아진다. 우선순위에 따라 타임 슬라이스가 다르다. 일반적으로 사용하는 방식이다.
우선순위 스케줄링: 선점형, 비선점형 알고리즘에 모두 사용할 수 있다.
인터럽트 처리
동기적 인터럽트: 프로세스가 실행중인 명령어로 인해 발생한다. (=사용자 인터럽트)
비동기적 인터럽트: 실행중인 명령어와 무관하게 발생한다. H/W적인 오류로 발생한다.
시스템에는 수많은 인터럽트가 존재하고 각각의 인터럽트에는 고유번호(IRQ)가 있다. 인터럽트가 여러개가 동시에 발생할수도 있는데 하나로 묶어서 처리하는 개념을 인터럽트 벡터라고 한다.
인터럽트 처리과정
- 인터럽트 발생시 현재 실행 중인 프로세스는 일시 정지가 되고 재시작을 위한 현재 프로세스 정보를 임시 저장한다
- 인터럽트 컨트롤러가 실행되어 처리 순서를 결정한다
- 먼저 처리할 인터럽트가 결정되면 인터럽트 벡터에 등록된 인터럽트 핸들러가 실행된다
- 인터럽트 핸들러가 처리를 마치면 일시 정지된 프로세서가 다시 실행되거나 종료된다
운영체제가 사용자 모드와 커널 모드를 전환하며 작업 처리를 하는 것을 이중 모드라고 한다. 이중 모드는 운영체제가 자원을 보호하기 위해 사용하는 기법이다.
[Chapter 5. 프로세스 동기화]
프로세스 간 통신(IPC): 같은 컴퓨터 내의 프로세스 뿐만 아니라 네트워크로 연결된 다른 컴퓨터와의 프로세스와의 통신도 포함된다.
바쁜 대기: 상태 변화를 살펴보기 위해 반복문을 무한 실행하며 대기하는 것
바쁜 대기를 해결하기 위해 동기화를 사용한다. 대기가 있는 통신은 동기화 통신, 대기가 없는 통신은 비동기화 통신이라고 한다.
IPC에서 가장 중요한 것은 프로세스 동기화이다.
IPC의 종류
- 전역 변수: 동기화 문제가 있기때문에 바쁜 대기로 계속 주시해야한다.
- 파일: 주로 부모-자식 관계 IPC에서 많이 사용된다. 운영체제가 프로세스 동기화를 제공하지 않아서 wait() sys-call을 이용해서 동기화를 한다.
- 파이프: 운영체제가 제공하는 동기화 통신 방식이다. 단방향 통신이기 때문에 양방향 통신을 하려면 파이프 2개를 사용해야 한다. 이름 없는 파이프는 부모-자식같이 서로 관련있는 IPC에 사용되고 이름 있는 파이프는 FIFO라는 특수 파일을 이용하여 서로 관련없는 IPC에 사용된다.
- 소켓: 네트워킹이라고 한다. 원격 프로시저 호출이나 소켓을 이용한다. 프로세스 동기화를 지원하고 하나만 사용해도 양방향 통신이 된다.
동기화를 지원하는 IPC에는 open()과 close()가 사용된다.
두개 이상의 프로세스가 공유 자원을 병행적으로 읽거나 쓰는 상황을 '경쟁 조건(race condition)이 발생했다' 고 한다.
임계구역(critlcal section): 공유 자원 접근 순서에 따라 실행 결과가 달라지는 프로그램의 영역. 임계구역에서는 프로세스들이 동시에 작업하면 안된다. 전역 변수 뿐만 아니라 하드웨어 자원을 사용할 때도 적용되는 개념이다.
생산자-소비자 문제(produce-consumer problem)
공유 변수에 두개 이상의 프로세스가 접근 타이밍을 맞추지 않고 동시에 접근해서 공유 변수의 값이 꼬여 race condition이 발생하는 것
임계구역 해결 조건
- 상호 배제(mutual exclusion): 한 프로세스가 임계구역에 들어가면 다른 프로세스는 임계구역에 들어갈 수 없다. race conditon은 상호 배제를 지키지 않아서 발생하는 문제이다.
- 한정 대기(bounded wating): 어떤 프로세스도 무한 대기하지 않아야 한다.
- 진행의 융통성(progress flexibility): 한 프로세스가 다른 프로세스의 진행을 방해해서는 안 된다.
임계구역 문제를 해결하는 단순한 방법은 잠금(lock)을 이용하는 것이다.
임계구역 해결 조건을 고려한 코드 설계
- 상호 배제 문제: 전역변수(lock)를 통해 임계구역을 잠구어 하나의 프로세스만 사용할 수 있게 한다. 하지만 임계구역에 진입 후 lock을 true로 바꾸기 직전에 타임아웃으로 준비상태에 들어간다면 이후 두 프로세스는 임계구역에 동시에 접근하게 된다. 또한 lock=true라면 다른 프로세스는 잠금이 풀리기를 기다리며 바쁜 대기를 하게된다.
- 한정 대기 문제: 두 프로세스가 lock을 사용해 임계구역에 진입전에 lock을 true로 바꾼다. 이렇게 하면 상호 배제는 보장되지만 두 프로세스가 각자의 lock을 true로 바꾸고 타임아웃 된 경우 모두 임계구역에 진입하지 못하는 무한 대기 현상이 발생한다. 한정 대기 조건을 보장하지 못하는 상황으로 '교착 상태(deadlock)' 라고 한다. 프로세스가 늘어나면 검사해야하는 lock의 개수가 늘어나서 비효율적이다.
- 진행의 융통성 문제: lock을 true/false가 아닌 정수값으로 둔다. 잠금을 확인하는 문장이 하나이므로 상호 배제와 한정 대기를 보장한다. 하지만 한 프로세서가 두 번 연달아서 임계구역에 접근하고 싶어도 그럴수 없다. 우선순위가 무시되고 이 때문에 특정 프로세스가 해당 프로세스를 방해하는 구조가 되고 이 현상을 경직된 동기화(lockstep synchronization)라고 한다.
- 하드웨어적인 해결 방법: 하드웨어의 지원을 받아서 검사와 지정을 한꺼번에 실행하여 임계구역을 보호할 수 있다. 편리하지만 바쁜 대기를 사용하여 검사하기 때문에 자원의 낭비가 있다.
피터슨 알고리즘: 한정 대기 문제에서 turn이라는 공유 변수를 추가한 것과 같다. 임계구역 해결의 세 가지 조건을 모두 만족하지만 2개의 포르세스만 사용 가능하다는 한계가 있다. 여러프로세스가 하나의 임계구역을 사용하려면 공유 변수를 추가하고 코드를 변경해야 한다.
데커 알고리즘
세마포어: 임계구역에 진입하기전에 스위치를 사용 중으로 놓고 임계구역으로 들어간다. 이후 도착하는 프로세스는 앞의 프로세스가 작업을 마칠때까지 기다리고 프로세스가 작업을 마치면 다음 프로세스에 임계구역을 사용하라는 동기화 신호를 보낸다. 다른 알고리즘과 달리 임계구역이 잠겼는지 직접 확인하거나, 바쁜 대기를 하거나, 다른 프로세스에 동기화 메시지를 보낼 필요가 없다.
하지만 세마포어의 P()나 V() 내부 코드가 실행되는 도중에 다른 코드가 실행되면 상호 배제와 한정 대기 조건을 보장하지 못하므로 검사와 지정을 사용하여 분리 실행되지 않고 완전히 실행되게 해야 한다.
공유 자원과 프로세서가 여러개 일때도 사용할 수 있다.
사용자가 잘못 사용하면 임계구역이 보호받지 못할 수도 있다.
모니터: 공유 자원을 내부적으로 숨기고 인터페이스만 제공함으로써 자원을 보호하고 프로세스 간의 동기화를 시킨다. sys-call과 같은 개념이다. 임계구역 보호와 동기화를 위해 내부적으로 상태 변수를 사용한다.
[Chapter 6. 교착 상태]
2개 이상의 프로세스가 다른 프로세스의 작업이 끝나기만을 기다리며 작업을 더 이상 진행하지 못하는 상태
교착 상태의 발생
- 시스템 자원: 다른 프로세스와 공유할 수 없는 자원을 사용할 때 발생한다.
- 공유 변수
- 응용 프로그램
교착 상태 필요조건
- 상호 배제: 한 프로세스가 사용하는 자원은 다른 프로세스와 공유할 수 없는 배타적인 자원이어야 한다.
- 비선점: 한 프로세스가 사용 중인 자원은 중간에 다른 프로세스가 빼앗을 수 없는 비선점 자원이어야 한다.
- 점유와 대기: 프로세스가 어떤 자원을 할당받은 상태에서 다른 자원을 기다리는 상태여야 한다.
- 원형 대기: 점유와 대기를 하는 프로세스 간의 관계가 원을 이루어야 한다.
위 네가지를 모두 충족해야 교착 상태가 발생하고 단 하나라도 만족하지 않으면 발생하지 않는다.
교착 상태와 기아 현상은 다르다. 기아 현상은 정책상 잘못이나 오류로 인해 발생하고 에이징으로 해결할 수 있지만 교착 상태는 자연적으로 발생하고 처리도 복잡하다.
교착 상태 해결 방법
- 예방: 필요 조건중 하나라도 무력화를 시킨다. 실효성이 적어 잘 사용되지 않는다.
- 회피: 자원 할당량을 조절하여 해결한다. 하지만 얼마만큼 할당해야 발생하지 않는다는 보장이 없기 때문에 실효성이 적다.
- 검출과 회복: 자원 할당 그래프를 모니터링하면서 교착 상태가 발생하는지 살펴보고 발생 시 회복 단계가 진행된다. 현실적인 접근 방법이다.
교착 상태 예방
- 상호 배제 예방: 독점적으로 사용할 수 있는 자원을 없애고 모든 자원을 공유시킨다. 임계구역이 보호받지 못하기 때문에 상호 배제 무력화는 사실상 어렵다.
- 비선점 예방: 모든 자원을 빼앗을 수 있도록 만든다. 하지만 임계구역을 보호하기 위해 잠금을 사용시 자원을 빼앗을 수 없을 뿐더러 상호 배제도 보장할 수 없다. 게다가 기아 현상이 발생한다.
- 점유와 대기 예방: 프로세스가 자원을 점유한 상태에서 다른 자원을 기다리지 못하게 하는 방법이다. 프로세스가 자원을 확보했는데 추가로 필요한 자원이 생기는 경우, 당장 사용하지도 않을 자원을 미리 선점하여 낭비하는 경우, 자원을 많이 사용하는 프로세스는 적게 사용하는 프로세스보다 자원을 동시에 확보하는게 어려워서 기아 현상이 발생하는 경우, 일괄 작업 방식으로 동작하는 여러 단점이 생긴다.
- 원형 대기 예방: 점유와 대기를 하는 프로세스들이 원형을 이루지 못하도록 막는 방법이다. 프로세스 작업 진행에 유연성이 떨어지고 자원의 번호를 어떻게 부여할 것인지에 대한 문제가 발생한다.
교착 상태 회피
교착 상태가 발생하지 않는 범위 내에서만 자원을 할당한다. 자원의 총 수와 현재 할당된 자원의 수를 기준으로 시스템을 안정 상태와 불안정 상태로 나누고 시스템이 안정 상태를 유지하도록 자원을 할당한다. 안정 상태를 유지할 수 있는 범위 내에서 자원을 할당함으로써 교착 상태를 피한다.
은행원 알고리즘
최악을 경우를 기준으로 잡아서 문제 상황을 철저히 피하여 교착 상태를 막는다.
각 프로세스의 기대 자원과 비교하여 가용 자원이 크거나 같은 경우가 한 번 이상인 경우 안정 상태이다.
이 알고리즘을 사용하려면 프로세스가 자신이 사용할 모든 자원을 미리 선언해야 하고 시스템의 전체 자원 수가 고정적이어야 하며, 자원이 낭비되는 단점이 있다.
교착 상태 검출
예방은 구현하기 어렵고 회피는 자원을 낭비하는 문제가 있어서 검출이 가장 현실적인 해결 방법이다.
- 타임 아웃을 이용한 교착 상태 검출
일정 시간동안 작업이 진행되지 않은 프로세스를 교착 상태가 발생한 것으로 간주하여 처리하는 방법이다.
쉽게 구현할 수 있지만 엉뚱한 프로세스가 강제 종료되거나(타임아웃≠교착상태) 모든 시스템에 적용할 수 없다는(네트워크 등) 문제가 있다. 가벼운 교착 상태 검출이라고 한다.
DB의 경우 일관성이 깨지면 안되기 때문에 OS보다 처리가 복잡하다. 그래서 체크포인트와 롤백을 사용한다.
- 자원 할당 그래프를 이용한 교착 상태 검출
OS는 자원을 요청하거나 할당할 때마다 자원 할당 그래프를 갱신하는데 이때 사이클이 발생하면 교착 상태가 검출된 것으로 판단한다. 오버헤드가 발생한다는 단점이 있다.
교착 상태 회복
교착 상태를 유발한 프로세스를 강제로 종료한다. 교착 상태를 일으킨 모든 프로세스를 동시에 종료시키거나 하나를 골라 순서대로 종료시키며 나머지 프로세스의 상태를 파악하는 방법을 사용한다.
[Chapter 7. 물리 메모리 관리]
메모리 관리의 이중성: 프로세스는 메모리를 독차지하려 하고 메모리 관리자 입장에서는 되도록 관리를 효율적으로 하고 싶어 하는 것
컴파일러는 기계어로 번역 후 한꺼번에 실행하고 인터프리터는 한 줄씩 번역하여 실행한다.
컴파일러의 사용 목적은 오류 발견 및 코드 최적화이다.
(소스코드->컴파일러->목적코드->링커)->실행 (괄호 안은 컴파일 과정)
메모리 관리자의 역할
- 가져오기: 프로세스와 데이터를 메모리로 가져온다
- 배치: 가져온 프로세스와 데이터를 메모리의 어떤 부분에 올려놓을지 결정한다
- 재배치: 메모리가 꽉 찬 경우 오래된 프로세스를 내보낸다 (LRU?)
배치 정책에서 메모리를 같은 크기로 자르는 것을 페이징, 프로세스의 크기에 맞게 자르는 것을 세그먼테이션이라고 한다.
메모리 관리자는 절대 주소를 사용하지만 사용자 입장에서 절대 주소(물리 주소)는 불편하고 위험하기때문에 사용자는 상대 주소(논리 주소)를 사용한다.
메모리 오버레이: 프로그램의 실제 크기가 메모리보다 클 때 전체 프로그램을 메모리에 가져오는 대신 적당한 크기로 잘라서(모듈) 가져오는 기법
모듈이 교체될 때 별도의 스왑영역(저장장치 공간)에 옮겨둔다. 저장장치는 장소만 빌려주고 관리는 메모리 관리자가 한다.
다중 프로그래밍 환경에서의 메모리 할당
가변 분할 방식: 연속된 공간에 배치할수 있다는 장점이 있지만 메모리 관리가 복잡하다.
빈 영역이 발생하더라도 서로 떨어져있으면 프로세스를 배정하지 못하기 때문에 큰 프로세스는 계속 할당받지 못해 기아 현상이 발생할 수 있다. 이로 인해 메모리에 작은 조각들이 발생하는 현상을 단편화/조각화 라고 한다. 이 문제를 해결하기 위해 메모리 배치 방식이나 조각 모음을 사용한다.
- 메모리 배치 방식: 최초 배치(단편화 고려x), 최적 배치, 최악 배치, 버디 시스템이 있다.
- 조각 모음: 단편화된 공간을 합치기 위해 프로세스의 동작을 멈추고 적당한 위치로 옮긴 후 상대 주소값을 바꾼다. 이후 프로세스를 다시 실행한다. 많은 시간이 걸린다.
- 버디 시스템: 가변+고정의 특징을 모두 가지고 있다.
고정 분할 방식: 메모리 관리가 수월하지만 낭비가 발생할 수 있다. 프로세스가 메모리의 여러 조각에 나뉘어 저장되는 것이 문제이다. 프로세스가 메모리 영역보다 작은 경우 내부 단편화가 발생한다.
현대 OS에서는 기본적으로 고정 분할 방식을 사용하고 일부분은 가변 분할 방식을 혼합하고 있다.
[Chapter 8. 가상 메모리의 기초]
가상 메모리: 물리 메모리의 크기와 상관없이 프로세스에 커다란 메모리 공간을 제공하는 기술
가상 메모리 시스템의 모든 프로세스는 물리 메모리와 별개로 0번지부터 시작하는 연속된 메모리 공간을 가진다. 논리 주소와 유사하지만 물리 공간에 비례하지 않고 가상의 주소 공간을 가진다.
가상 메모리에서 메모리 관리자가 사용할 수 있는 메모리의 전체 크기는 물리 메모리+스왑 영역을 더한 크기이다. (=동적 주소 변환)
세그먼테이션(가변) 또는 페이징(고정) 기법을 단독으로 사용하기엔 단점이나 어려움이 있어서 잘 사용되지 않고 두 기법의 단점을 보완한 세그먼테이션-페이징 혼용 기법을 주로 사용한다.
매핑 테이블
가상 주소는 물리 주소나 스왑 영역 한 곳에 위치하며, 메모리 관리자는 가상 주소와 물리 주소를 일대일 매핑 테이블로 관리한다. 세그먼테이션, 페이징 어떤 것이든 분할된 경우 똑같은 방식으로 적용된다.
페이징 기법
주소 변환 과정
가상->물리: 가상 주소가 어느 페이지에 있는지 찾고 해당 페이지에 가서 어느 프레임에 있는지 알아낸다.
물리->가상: 위와 과정은 같다.
정형화된 주소 변환
페이징 기법에서는 가상 주소를 VA=<P,D>로 표현한다.(P:페이지, D:거리)
페이징 기법에서의 주소 변환은 VA=<P,D>를 PA=<F,D>로 변환하는 것이다.(F:프레임, D:거리)
페이지 테이블을 이용하면 간단하게 가상 주소를 물리 주소로 변환할 수 있다. 페이지 테이블은 페이지 번호, 프레임 번호로 구성되고 각각의 한줄은 페이지 테이블 엔트리(PTE)라고 부른다.
가상 주소를 <P,D>로 변환하는 공식
P=VA / PAGE_SIZE
D=VA % PAGE_SIZE
페이지 테이블 관리
페이지 테이블은 프로세스마다 하나씩 가지기 때문에 여러개의 프로세스가 실행시 전체 페이지 테이블의 크기는 그에 비례해서 커지기 때문에 사용할 수 있는 메모리 영역이 줄어든다. 따라서 페이지 테이블의 크기를 적정하게 유지하는 것이 페이지 테이블 관리의 핵심이다. 페이지 테이블에 빠르게 접근하기 위해 레지스터가(PTBR) 존재하고 각 페이지 테이블의 시작 주소를 PTBR에 보관한다. PTBR은 프로세스의 제어 블록에 저장된다.
페이지 테이블 매핑 방식
직접 매핑, 연관 매핑, 집합-연관 매핑, 역매핑이 있다.
- 직접 매핑: 모든 페이지 테이블을 물리 메모리에 가지고 있는 가장 단순한 방식. 주소 변환 속도가 빠르다
- 연관 매핑: 전체 페이지 테이블을 스왑 영역에 두고 페이지 테이블의 일부를 물리 메모리에 가져오는 방식. 원하는페이지가 TLB에 있는경우 곧바로 물리 주소로 변환되고 없는 경우 스왑 영역에 저장된 직접 매핑 테이블을 사용하여 프레임 번호로 변환한다. 전체 페이지 테이블을 물리 메모리에 보관하지 않아서 메모리를 절약할 수 있지만 TLB 미스가 빈번하게 발생하면 시스템의 성능이 떨어진다.
- 집합-연관 매핑(디렉터리 매핑): 페이지 테이블을 같은 크기의 여러 묶음으로 나누고 각 묶음의 시작 주소를 가진 디렉터리 테이블을 새로 만들어 관리한다. 가상 주소를 VA=<P,D>가 아닌 VA=<P1,P2,D>로 표시한다. 두단계를 거쳐서 물리 주소로 변환된다.
- 역매핑: 물리 메모리의 프레임 번호를 기준으로 테이블을 작성한다. 프로세스의 수와 상관없이 항상 일정 크기의 페이지 테이블을 유지하여 크기가 매우 작다. 연관 매핑과 마찬가지로 시스템의 성능이 떨어질 수 있다.
세그먼테이션 기법
세그먼테이션 기법도 매핑 테이블을 사용한다. 페이징 기법에서는 크기가 모두 똑같기때문에 매핑 테이블이 크기 정보를 갖고있을 필요가 없었지만 세그먼테이션 기법은 가변적이기 때문에 크기 정보를 포함한다.
가상 주소를 VA=<S,D>로 표현한다.(S:세그먼트 번호, D:거리)
세그먼테이션 테이블의 limit은 메모리를 보호하는 역할을 한다. limit을 넘어서 접근하려고 하면 트랩을 발생시키고 프로세스를 강제 종료시킨다. 트랩이 발생하면 OS는 사용자에게 segmentation fault 메시지를 보낸다.
(트랩의 반대는 시그널)
세그먼테이션-페이징 혼용 기법
메모리 접근 권한 검사는 가상 주소에서 물리 주소로 주소 변환이 일어날 때마다 시행된다.
페이징 기법에 세그먼테이션 테이블을 추가하여 권한 비트와 같이 중복되는 데이터를 세그먼테이션 테이블로 옮겨오면 테이블의 크기를 줄일 수 있다. 현재 대부분의 운영체제는 이 방식을 사용하고 있다.
세그먼테이션-페이징 혼용 기법의 주소 변환
가상 주소를 VA=<S,P,D>로 표현한다.(S:세그먼트 번호, P:페이지 번호, D:거리)
[Chapter 9. 가상 메모리 관리]
요구 페이징: 프로세스가 요청할 때 메모리로 가져오는 것
미리 가져오기: 앞으로 필요할 것이라 예상되는 페이지를 미리 가져오는 것. (캐시)
PTE의 플래그 비트에는 접근, 변경, 유효, 읽기, 쓰기, 실행 비트 등이 모여있다.
페이지 부재
프로세스가 페이지를 요청했을 때 그 페이지가 메모리에 없는 상황.
유효비트가 0일때 페이지가 메모리에 있고 1일때는 스왑 영역에 있다. 메모리에 빈 프레임이 있을 경우 스왑 영역에서 가져오기만 하면 되지만 빈 프레임이 없는 경우 메모리에 있는 프레임 중 하나를 스왑 영역으로 보낸 후에야 가져올 수 있다. 이것을 결정하는 알고리즘을 페이지 교체 알고리즘 이라고 한다.
지역성
- 시간적 지역성: 한번 참조된 항목은 곧바로 다시 참조되는 경향이 있다.
- 공간적 지역성: 참조된 항목 근처의 다른 항목들이 곧바로 다시 참조될 가능성이 높다.
- 순차적 지역성: 여러 작업이 순서대로 진행되는 경향이 있다. 공간적 지역성의 특별한 경우로 본다.
페이지 교체 알고리즘
- 무작위: 특별한 알고리즘 없이 무작위로 선정한다. 지역성을 전혀 고려하지 않기 때문에 성능이 좋지 않아 잘 사용하지 않는다.
- FIFO: 큐로 구현한다. 큐의 맨 위의 페이지는 가장 오래된 페이지이고 메모리가 꽉 차면 맨 위의 페이지가 스왑 영역으로 나간다. 시간적 지역성을 고려하면 가장 오래된 페이지를 스왑 영역으로 내보내는게 맞지만 오래되었더라도 자주 사용되는 페이지도 스왑 영역으로 내보내게 된다.
- 최적: 앞으로 사용하지 않을 페이지를 스왑 영역으로 옮긴다. 미래의 메모리 접근 패턴을 보고 대상 페이지를 결정하기 때문에 성능이 좋지만 미래의 접근 패턴을 안다는 것은 불가능하기 때문에 실제로 구현할 수 없다. 하지만 과거의 데이터를 바탕으로 미래를 추정하는것은 가능하기 때문에 최근 최소 사용(LRU), 최소 빈도 사용(LFU), 최근 미사용(NUR)이 개발되었고 성능도 유사하게 나오기에 이들을 최적 근접 알고리즘이라고 한다.
- LRU(least recently used): 메모리에 올라온 후 가장 오랫동안 사용되지 않은 페이지를 스왑 영역으로 옮긴다. 페이지에 접근한 시간이나 카운터를 사용하여 구현하거나 참조 비트 시프트를 사용하여 구현할 수 있다. 실제로는 참조 비트 시프트를 이용하여 구현하고 참조 횟수가 아닌 참조 시간을 기준으로 대상 페이지를 선정한다. 적지 않은 공간을 사용하므로 낭비되는 메모리 공간이 생긴다.
- LFU(least frequently used): 현재 프레임에 있는 페이지마다 그동안 사용된 횟수를 세어 횟수가 가장 적은 페이지를 스왑 영역으로 보낸다. LRU와 마찬가지로 낭비되는 메모리 공간이 많다.
- NUR(not used recently): LRU, LFU와 성능이 거의 비슷하면서 불필요한 메모리 낭비 문제를 해결한 알고리즘이다. 페이지마다 참조 비트와 변경 비트를 가지므로 페이지마다 추가되는 공간이 2비트 뿐이다. 참조 비트는 PTE의 접근 비트를 가리키고 변경 비트는 PTE의 변경 비트를 가리킨다. 각 비트의 초기값은 0이고 페이지에 접근하면 참조 비트는 1이 되고 페이지가 변경되면 변경 비트는 1이 된다. 참조 비트->변경 비트순으로 고려하여 대상 페이지를 결정한다. 모든 페이지의 비트가 1,1이라면 정상적으로 이용할 수 없으므로 이런 경우 모두 0,0으로 초기화한다. 쉽게 구현할 수 있다는 장점 때문에 가장 많이 사용된다.
FIFO 변형: FIFO의 단점을 개선한 알고리즘
- 2차 기회: 특정 페이지에 접근하여 페이지 부재 없이 성공할 경우 해당 페이지를 큐의 맨 뒤로 이동시켜 대상 페이지에서 제외시킨다. 성공한 페이지를 큐의 맨 뒤로 옮김으로써 기회를 한번 더 주는것과 같다. 성능은 LRU, LFU, NUR보다 약간 낮고 FIFO보다 약간 높다. 큐를 유지하는 비용이 높고 페이지가 성공하면 큐의 중간의 있는 값들을 뒤로 이동시키는 작업이 추가되는 단점이 있다.
- 시계: 2차 기회와 유사하다. 큐 대신 원형 큐를 사용한다. 마찬가지로 페이지가 성공하면 기회를 한번 더 주기위해 참조 비트를 추가한다. 대상 포인터와 페이지당 참조 비트 하나만 추가하면 되기 때문에 NUR보다 추가 공간이 적게 들지만 복잡하고 계산량이 많다는 단점이 있다.
스레싱과 프레임 할당
스레싱: 하드디스크의 입출력이 너무 많아져서 잦은 페이지 부재로 인해 작업이 멈춘 것 같은 상태.
멀티프로그래밍 정도(degree of multiprogramming): 동시에 실행하는 프로그램의 수. 너무 높으면 스레싱이 발생한다.
프로세스에 프레임을 할당하는 방식
정적 할당: 프로세스 실행 초기에 프레임을 나누어준 후 그 크기를 고정하는 것
- 균등 할당: 프로세스의 크기와 상관없이 사용 가능한 프레임을 모든 프로세스에 동일하게 할당한다. 크기가 큰 프로세스의 경우 필요한 만큼 프레임을 할당받지 못해 페이지 부재가 빈번하게 발생하고 작은 프로세스의 경우 메모리가 낭비된다.
- 비례 할당: 프로세스의 크기에 비례하여 프레임을 할당한다. 균등 할당보다 조금 더 현실적이지만 프로세스가 실행중에 필요로 하는 프레임을 유동적으로 반영하지 못하고 사용하지도 않을 메모리를 처음부터 미리 확보하여 공간을 낭비한다.
동적 할당: 실시간으로 변하는 요청을 수용한다
- 작업집합 모델: 지역성 이론을 바탕으로 최근 일정 시간동안 참조된 페이지들을 집합으로 만들고, 이 집합에 있는 페이지들을 물리 메모리에 유지하여 프로세스의 실행을 돕는다. 작업집합 윈도우의 크기에 따라 프로세스의 실행 성능이 달라진다.
- 페이지 부재 빈도: 페이지 부재 횟수를 기록하여 페이지 부재 비율을 계산한다. 상한선과 하한선을 설정한 후 상한선을 초과하면 할당된 프레임이 적다는 것을 의미하므로 프레임을 추가하고 하한선 밑으로 내려가면 메모리가 낭비되므로 할당한 프레임을 회수한다.
[Chapter 10. 입출력 시스템과 저장장치]
여러 주변장치는 메인보드 내의 버스로 연결된다.
데이터가 지나다니는 하나의 통로를 채널이라고 부른다. 속도가 비슷한 장치끼리 묶어서 채널을 할당하면 전체 데이터 전송 속도를 향상시킬 수 있다.
폴링->I/O제어기->입출력 버스 분리
CPUㅡ메모리(메인 버스), CPUㅡVGA(그래픽 버스), 고속/저속 입출력 버스를 사용한다.
하나의 버스 채널은 주소 버스, 데이터 버스, 제어 버스로 구성된다.
직접 메모리 접근(DMA): CPU의 도움 없이도 메모리에 접근할 수 있도록 입출력 제어기에 부여된 권한
입출력 제어기는 여러 채널에 연결된 주변 장치로부터 전송된 테이터를 적절히 배분하여 하나의 데이터 흐름을 만들고 이 때 채널 선택기는 여러 채널에서 전송된 데이터 중 어떤 것을 메모리로 보낼지 결정하고 DMA 제어기를 거쳐 메모리로 올라간다. CPU와 DMA 제어기의 작업 공간이 겹치기 때문에 메인 메모리의 주소 공간 중 일부를 DMA 제어기에 할당하여 작업 공간이 겹치는 것을 막는다.
입출력 제어기와 DMA 제어기의 협업으로 작업이 완료되면 입출력 제어기는 CPU에 인터럽트를 보낸다.
외부에서 발생시 인터럽트, 내부에서 발생시 예외, 사용자가 임의로 발생시킨 경우 시그널이다. 예외 발생시 어떤 상황에서 오류가 발생했는지 파악하기 위해 프로세스가 종료되기 직전까지의 메모리와 레지스터 상태를 저장하는데 이를 코어 덤프라고 한다.
인터럽트 벡터: 여러 인터럽트 중 어떤 인터럽트가 발생했는지 파악하기 위해 사용하는 자료구조
인터럽트 핸들러: 인터럽트의 처리 방법을 함수 형태로 만든 것
버퍼: 바구니를 생각하면 된다. 단일 버퍼보다는 이중 버퍼가 버퍼 운용에 유리하다.
디스크 장치
디스크 장치를 사용하는 데에는 파티션, 포매팅, 조각 모음과 같은 관리 기법이 필요하다.
네트워크 저장 장치: DAS, NAS, SAN
디스크 스케줄링: 트랙의 이동을 최소화하여 탐색 시간을 줄이는 데 목적이 있다.
- FCFS(first come, first service): 요청이 들어온 트랙 순서대로 서비스한다. 별다른 기법을 사용하지 않고 요청된 트랙 번호 순서대로 매우 큰 폭으로 바쁘게 움직인다.
- SSTF(shortest seek time first): 현재 헤드가 있는 위치에서 가장 가까운 트랙부터 서비스한다. 효율성은 좋지만 기아 현상을 일으킬 수 있다.
- 블록 SSTF: 에이징을 사용하여 SSTF의 기아 현상을 어느정도 해결한 방법으로 모든 트랙이 블록 안에서만 움직인다.
- SCAN: SSTF의 공평성 위배 문제를 완화하기 위해 만들어졌다. 헤드가 한 방향으로만 움직이고 맨 마지막 트랙에 도착할 때 까지 뒤돌아가지 않는다. SSTF보다 성능이 조금 떨어지지만 FCFS보다 우수하다.
- C-SCAN(circular SCAN): SCAN을 변형하여 헤드가 한쪽 방향으로 움직일때는 요청받은 트랙을 서비스하고 반대 방향으로 돌아올때는 서비스하지 않고 이동만 한다. 동일한 트랙 요청이 연속적으로 발생하면 마찬가지로 기아 현상이 발생한다.
- LOOK: 더 이상 서비스할 트랙이 없으면 헤드가 끝까지 가지 않고 중간에서 방향을 바꾼다. 많이 사용된다.
- C-LOOK(circular LOOK): C-SCAN의 LOOK 버전이다.
- SLTF(shortest latency time first): 최소 지연 우선 기법. 헤드가 고정된 저장장치에 사용된다.
RAID(redundant array of independent disks): 자동으로 백업을 하고 장애가 발생하면 이를 극복하는 시스템. 동일한 규격의 디스크를 여러 개 모아 구성하며, 장애가 발생했을 때 데이터를 복구하는 데 사용된다.
- RAID 0(스트라이핑): 같은 규격의 디스크를 병렬로 연결해서 이론적으로 입출력 속도가 빠르다. 복구 기능이 없다.
- RAID 1(미러링): 같은 크기의 디스크를 최소 2개 이상 필요로 하고 짝수 개의 디스크로 구성된다. 비용이 증가하고 속도가 느려질 수 있다는 단점이 있다.
- RAID 2: 오류 교정 코드(ECC)를 사용하여 오류를 찾고 교정을 한다. n개의 디스크에 대해 n-1개의 추가 디스크를 필요로 하고 오류 교정 코드를 계산하는 데 많은 시간을 소비하므로 잘 사용되지 않는다.
- RAID 3: 오류 검출 코드를 사용하여 데이터를 복구한다. 섹터 단위로 데이터를 나누어 저장한다. N-way 패리티 비트를 구성하는 데 필요한 계산량이 많다는 단점이 있다.
- RAID 4: RAID 3과 같은 구조이지만 처리 단위가 섹터가 아닌 블록이다. 데이터의 병목 현상때문에 사용하지 않는다.
- RAID 5: RAID 4와 같은 방법을 사용하지만 병목 현상을 해결했다. 디스크 2개에 동시에 장애가 발생하면 복구가 불가능하다.
- RAID 6: RAID 5와 같은 방식이지만 패리티 비트가 2개이다. RAID 5보다 계산량이 많고 4개의 디스크당 2개의 추가 디스크가 필요하다는 단점이 있다.
- RAID 10: RAID 0과 RAID 1을 결합한 방식이다. 최소 4개의 디스크가 필요하다.
- RAID 50, 60: RAID 0과 RAID 5, 6을 결합한 방식이다. RAID 10에 비해 추가되는 디스크의 수가 적지만 입출력 시 계산량이 증가한다