하드웨어 인터럽트
바로 잡을 부분은 설명에 운영체제에 시스템 콜을 요청한다는 내용이 있는데
하드웨어 인터럽트는 외부 장치(키보드, 마우스)가
CPU에 직접 신호를 보내는 것이고,
CPU는 이 신호를 받아 인터럽트 벡터 테이블이란 것을 참조해서
ISR(인터럽트 처리 루틴)을 실행한다.
시스템 콜은 하드웨어가 아닌 소프트웨어(응용 프로그램)가
운영체제에 서비스를 요청할 때 사용하는 방식이다.
인터럽트 라인: CPU에 연결된 "비상벨 울려주는 선 (물리적인 통로)"
인터럽트 벡터 테이블: 비상 연락처 목록
| 신호 번호 1번 → 키보드 처리 코드 위치 |
| 신호 번호 2번 → 타이머 처리 코드 위치 |
| 신호 번호 3번 → 마우스 처리 코드 위치 |
CPU가 인터럽트 신호를 받으면 이 목록을 펼쳐서
"이 신호는 어디서 처리하지?"를 찾는다.
ISR (인터럽트 처리 루틴): 실제로 처리하는 코드
순서 흐름
IO 장치에서 신호 발생
↓
인터럽트 라인을 통해 CPU에 전달
↓
CPU가 현재 실행 중이던 명령을 중단, 상태 저장
↓
인터럽트 벡터 테이블에서 해당 ISR 주소 조회
↓
ISR 실행 (OS 커널 코드) → 디바이스 컨트롤러의 로컬 버퍼 접근
↓
처리 완료 후 원래 실행 지점으로 복귀
디바이스 컨트롤러는 외부 장치와 CPU 사이의 통역사이다.
키보드는 키가 눌릴 때 발생하는 미세한 전기적 변화를 감지하는 반면
CPU는 매우 정교하게 정해진 클럭 주기에 맞춰서 고속으로
디지털 신호를 주고 받기에 CPU 내부 회로를 수만 가지 주변기기의
전기적 규격에 모두 맞게 설계하는 것은 물리적으로 불가능하며
효율성도 극도로 떨어지기에
디바이스 컨트롤러가 외부 장치의 고유한 전기 신호를 받아 디지털 데이터로 변환해서
CPU가 이해할 수 있는 공통 규격으로 맞춰준다.
캐시 추가 설명
CPU Core (ALU): 실제 연산을 수행하는 곳 (가장 빠름)
레지스터: CPU 내부의 아주 작은 임시 저장소 (연산에 즉각 사용)
L1/L2/L3 Cache: CPU와 메모리 사이의 속도 차이를 줄이는 완충 지대
Main Memory (RAM): 현재 실행 중인 프로그램이 올라가는 곳
Storage (SSD/HDD): 데이터가 영구 저장되는 곳 (가장 느림)
메모리와 CPU 사이에 레지스터 계층을 둬서 속도 차이를 해결한다?
CPU는 데이터를 메모리(RAM)에서 직접 가져와 연산하려 한다.
메모리는 CPU의 연산 속도보다 수백 배 느리다.
CPU가 메모리에서 데이터를 가져오는 동안 CPU는 손가락 빨며 기다려야 한다.
해결: CPU 내부에 가장 빠른 저장소(레지스터)를 만든다.
일단 데이터를 메모리에서 레지스터로 옮겨 놓으면
CPU는 레지스터에 있는 데이터를 가지고 자기 속도에 맞춰
초고속으로 연산할 수 있다.
캐싱 계층이라는 것은 절대적인 어떤 개념보다는 관계의 이름이다.
캐싱이라는게 말 그대로 느린 장치에 있는 데이터 중 자주 쓰는 것만
추려서 빠른 장치에 복사해두고, 사용하는 행위인데
주기억 장치가 보조기억장치의 캐싱 계층이라 하는 것도
만약에 게임을 실행하거나 인텔리제이 킬 때 로딩이 돌아가는데
이것은 느린 SSD에 있는 데이터를 빠른 RAM(메모리)로 복사하는 과정이고,
CPU는 SSD에 직접 접근하지 않고도 RAM에 올라온 데이터를 읽는다.
이때 RAM은 SSD를 위한 캐시 역할을 하는 것이다.
문제점: CPU 연산 속도에 비해 메인 메모리(RAM)의 데이터 전송 속도가 너무 느림 (CPU의 병목 현상 발생).
해결책: 두 계층 사이의 극심한 속도 차이를 완화하기 위해
고속 하드웨어인 L1, L2, L3 캐시 메모리를 배치함.
캐싱 계층은 특정 하드웨어 하나를 지칭하는 말이 아니라, 두 계층 간의 상대적인 관계를 부르는 명칭이다.
하위 계층(느린 장치)의 데이터 중 자주 사용하는 것만
추려서 상위 계층(빠른 장치)에 미리 복사해 두고 완충 작용을 하도록
만든 모든 중간 단계를 뜻함. (예: RAM은 SSD의 데이터를 미리 올려두는 캐시 역할을 수행함)
스와핑 보충 설명
| 용어 | 실제 의미 |
|---|---|
| 가상 메모리 | OS가 프로세스에게 "RAM이 무한한 것처럼" 착각시키는 주소 공간 |
| RAM (물리 메모리) | 실제로 CPU가 직접 접근 가능한 메모리 |
| 페이지 | 가상 메모리를 일정 크기로 나눈 단위 |
| 프레임 | RAM을 페이지와 같은 크기로 나눈 단위 |
| 페이지 테이블 | "가상 주소 → 실제 RAM 주소" 매핑 정보를 담은 표 |
| 디스크 (스왑 영역) | RAM 대신 임시로 페이지를 보관하는 저장소 |
CPU가 가상 주소 접근
│
▼
페이지 테이블 확인
│
┌────┴────┐
RAM에 있음 RAM에 없음
│ │
정상 접근 페이지 폴트 발생
│
▼
OS에 트랩(trap) 전달 (운영체제에 제어권 넘어감.)
│
▼
RAM에 빈 프레임 있음?
┌─────┴─────┐
있음 없음
│ │
│ 페이지 교체 알고리즘으로
│ 희생 페이지 선택 → 디스크의 스왑 영역으로 쫒아냄. (해당 램 프레임 비움.)
│ │
└─────┬──────┘
▼
이제 비어 공간이 확보된 RAM 프레임에,
처음 요청했던 데이터를 디스크에서 읽어와 적재
│
▼
페이지 테이블 갱신
(페이지가 위치하게 된 실제 RAM 프레임 번호와 가상 주소 매핑, 유효 비트를 1로 변경)
│
▼
중단됐던 명령어 재실행
(운영체제가 CPU에 제어권 돌려주면 트랩 유발했던 명령어를 다시 처음부터 실행,
이때 RAM에 데이터가 존재하므로 정상 접근 완료.)
왜 트랩이 발생할까?
왜 OS가 디스크에서 "사용하지 않는 프레임"을 찾나?
정확히는 디스크가 아니라 RAM에서 비울 프레임을 찾는 것이다.
빈 프레임이 없으면 기존 페이지를 디스크로 내보내야 하기 때문이다.
책에 나온 "실제 디스크로부터 사용하지 않은 프레임을 찾는다"는
설명은 조금 수정 되어야 할 것 같다.
정확한 순서는 RAM에서 교체할 프레임을 선택 -> 해당 내용 디스크에 저장
-> 필요한 페이지를 디스크에스 RAM으로 로드.
페이지 교체 알고리즘 내용도 조금 추가? 수정? 되어야 할 부분이
프레임을 실제 메모리에 가져와서 페이지 교체 알고리즘 기반으로
특정 페이지와 교환한다 보다는
데이터를 디스크에서 가져오기 전에 RAM에 빈 공간 있는지 먼저 확인하고,
빈 공간이 없을 때만 페이지 교체 알고리즘을 실행하여 공간 확보한 뒤
디스크에서 데이터를 가져오는 것이다.
CPU 스케줄링 알고리즘
CPU 스케줄링 알고리즘
│
├── 비선점형 (Non-preemptive)
│ ├── FCFS
│ ├── SJF
│ └── 우선순위 (Priority) ← 선점/비선점 둘 다 가능
│
└── 선점형 (Preemptive)
├── Round Robin (RR)
├── SRTF
└── 다단계 큐 (Multilevel Queue)
| 용어 | 의미 |
|---|---|
| 준비 큐 (Ready Queue) | CPU 할당을 기다리는 프로세스 대기열 |
| 선점 (Preemptive) | OS가 강제로 CPU 회수 가능 |
| 비선점 (Non-preemptive) | 프로세스가 스스로 CPU 반납할 때까지 대기 |
| 컨텍스트 스위칭 (Context Switching) | CPU가 다른 프로세스로 전환할 때 현재 상태 저장/복원 |
| 기아 현상 (Starvation) | 특정 프로세스가 계속 CPU를 못 받는 현상 책 원문에서의 긴시간 가진 프로세스가 실행되지 않는다 현상 부분 |
| 에이징 (Aging) | 오래 기다린 프로세스의 우선순위를 점진적으로 높이는 기법 |
스케줄링 목표
1. CPU 이용률 ↑ → CPU가 놀지 않게
2. 처리량 ↑ → 단위 시간당 처리 프로세스 수 많게
3. 대기 시간 ↓ → 준비 큐에서 기다리는 시간 짧게
4. 응답 시간 ↓ → 요청 후 첫 응답까지 시간 짧게
비선점형 알고리즘
FCFS (First Come First Served)
도착 순서대로 실행 (줄 서기)
[P1(24ms)] → [P2(3ms)] → [P3(3ms)]
↑ P1이 먼저 왔으면 24ms 동안 P2, P3는 무조건 대기
FCFS는 오직 도착한 순서대로만 CPU를 할당하는 방식이다.
가장 큰 특징은 긴 프로세스가 CPU를 잡으면 뒤에 있는
짧은 프로세스들이 무한정 대기하게 된다는 점이다.
SJF (Shortest Job First)
실행시간이 가장 짧은 프로세스 먼저
[P1(24ms)] [P2(3ms)] [P3(3ms)] 가 있다면
→ [P2(3ms)] → [P3(3ms)] → [P1(24ms)] 순 실행
평균 대기시간 이론상 최소.
기아 현상: 긴 프로세스는 영원히 실행 안 될수도 있음.
실행 시간 예측 불가: 실제로는 과거 실행 시간 기반으로 지수 평균으로 추정.
이론상 최소인 이유는 짧은 작업을 먼저 빼줄수록 뒤 프로세스들의
대기시간 합이 줄어들기 때문이다. (수학적으로 증명됨)
우선순위 스케줄링 (Priority Scheduling)
각 프로세스에 우선순위 번호 부여 → 높은 우선순위 먼저
SJF도 사실 "실행시간이 짧을수록 우선순위 높음"으로 볼 수 있음
→ SJF는 우선순위 스케줄링의 특수한 케이스
기아 현상을 해결하기 위해 에이징 방법 사용
-> 대기 시간이 길어질수록 우선순위를 점진적으로 높임.
우선순위 스케줄링은 선점형/비선점형 둘 다 구현 가능
비선점형: 더 높은 우선순위가 와도 현재 프로세스 완료 후 전환
선점형: 더 높은 우선순위 도착 시 즉시 CPU 회수
선점형 알고리즘
라운드 로빈 (Round Robin)
Time Quantum(q) = 4ms, 프로세스 3개(N=3) 예시
[P1][P2][P3][P1][P2][P3]...
4ms 4ms 4ms 4ms ...
자기 차례까지 최대 대기시간 = (N-1) × q = 2 × 4 = 8ms
q가 너무 크다 → 사실상 FCFS와 동일
q가 너무 작다 → 컨텍스트 스위칭 폭발 → 오버헤드 증가
(실제 작업보다 전환 비용이 더 커짐)
응답 시간이 짧다. (현대 OS 기본)
로드밸런서 트래픽 분산에도 활용.
전체 작업 완 시간은 길어질 수도 있다.
SRF (Shortest Remaining Time First)
SJF의 선점형 버전
실행 중 더 짧은 프로세스 도착 시 → 즉시 CPU 회수
P1(7ms 남음) 실행 중 → P2(4ms)가 도착
→ P1 중단, P2 먼저 실행 → P2 완료 후 P1 재개
이론상 평균 대기시간 최소
(컨텍스트 스위칭 오버헤드를 배제하고, 평균 시간은 SRF가 빠르다.)
(SJF가 최적이라고, 불리는 조건은 모든 프로세스가 동시에 도착했을 뿐인데
실제로 프로세스들이 각기 다른 시간이 도착하는 실제 환경에서는
SRF가 평균 대기 시간을 더 극단적으로 줄인다.)
기아 현상 (SJF보다 심각할 수 있음)
잦은 컨텍스트 스위칭
다단계 큐 (Multilevel Queue)
우선순위별로 큐를 분리
큐1 (최고 우선순위) : 시스템 프로세스 → FCFS
큐2 (중간 우선순위) : 대화형 프로세스 → RR
큐3 (낮은 우선순위) : 배치 프로세스 → FCFS
↓
높은 큐가 비어야만 낮은 큐 실행
스케줄링 오버헤드 낮음 (큐마다 다른 알고리즘 적용)
큐 간 이동 불가 -> 유연성 부족, 기아 현상 가능.