컴퓨터 구조를 배워야하는 이유
- 문제해결 능력을 키울 수 있다.
- 성능, 비용, 용량을 고려하여 개발할 수 있다.
컴퓨터의 구성 요소들
메인보드 안
- CPU
- 메모리에 저장된 값을 읽고, 해석, 실행
- ALU(계산기) + 제어장치(제어신호 송신, 명령어 해석) + 레지스터(CPU 내부 작은 저장소)
- ALU
- 레지스터 ➡️ (연산할 데이터) ➡️ ALU
- 제어장치 ➡️ (제어 신호) ➡️ ALU
- ❇️(위의 과정으로 연산 후 ) ALU ➡️ (연산 결과) ➡️ 레지스터
- 제어장치
- 플래그 레지스터 ➡️ (플래그) ➡️ 제어장치
- 명령 레지스터 ➡️ (해석할 명령어) ➡️ 제어장치
- (시스템버스의 제어버스) 제어신호 ➡️ 제어장치
- ❇️(위의 과정 이후) 제어장치 ➡️ (제어 신호) ➡️ 레지스터 / ALU / 메모리 / IO장치 (시스템 버스의 제어 버스를 통해)
- 레지스터
- 프로그램 카운터 PC
- 메모리에서 가져올 명령어의 주소
- 명령어를 실행할 때마다 위치 바뀜
- 명령어 레지스터 IR
- (현재 PC가 가르키고 있는 )현재 해석할 실행 중인 명령어를 저장
- 메모리 주소 레지스터 MAR
- CPU가 메모리 안에 있는 데이터를 사용할 때, 해당 데이터의 메모리 주소를 저장
- 시스템 버스 중 주소 버스와 연결된 레지스터
- 메모리 버퍼 레지스터 MBR
- (메모리, 입출력 장치같은 다른 장치들로 전송하기 위해,) CPU에서 읽거나 쓴 데이터를 저장
- 플래그 레지스터 FR
- 명령어 실행 중 발생하는 상태 정보를 저장
- 범용 레지스터 General-Purpose Register
- 데이터를 임시 보관, 자유롭게 사용 가능
- EAX :연산 결과를 저장
EBX : 범용 데이터 저장
ECX : 반복적인 명령어
EDX : 입출력 명령어
ESI, EDI : 메모리 데이터 복사
EBP, ESP : 스택 메모리의 주소 저장
- 스택 포인터 SP
- 메모리 내 스택 영역의 최상단 주소를 가르킴
- 베이스 레지스터 BR
- 베이스 주소를 저장
- 프로그램 카운터 PC
베이스 주소란?
메모리 주소는 베이스 주소와 오프셋으로 이루어져 있음
에를 들어, 배열에서 배열의 시작 주소가 베이스 주소가 되고, 배열의 나머지 요소들은 베이스 주소와 오프셋을 더해 주소를 구할 수 있음. 이 베이스 주소가 베이스 레지스터에 저장되고, 배열의 요소들은 베이스 레지스터에 저장된 베이스 주소와 오프셋의 결합으로 위치를 구할 수 있음. (베이스 레지스터 주소 지정 방식)
변위 주소 지정 방식?
1. 상대 주소 지정 방식 (PC를 이용한 변위 주소 지정 방식) : 오퍼랜드 필드(변위) + PC 값 = 유효 주소
2. 베이스 레지스터 주소 지정 방식 (위에서 기술) : 베이스 레지스터 + 오퍼랜드 필드(변위) = 유효 주소
-
- 플래그 레지스터의 종류
- 부호 플래그 (SF, Sign Flag) : 연산한 결과의 부호
- 제로 플래그 (ZF, Zero Flag) : 연산 결과가 0인지
- 캐리 플래그 (CF, Carry Flag) : 최상단 비트의 올림(캐리) 발생 여부
- 오버플로우 플래그 (OF, Overflow Flag) : 오버플로우(비트 초과) 발생 여부
- 인터럽트 플래그 (IF, Interrupt Flag) : 인터럽트의 가능 여부
- 슈퍼바이저 플래그 (Superviser Flag) : 커널 모드로 실행 중인지
- 플래그 레지스터의 종류
- 메모리
- 주소와 명령어(OP 코드), 데이터를를 저장
- 프로그램이 실행 되려면 메모리에 저장되어야 함
- 휘발성 저장장치
- 시스템버스
- 각 장치들이 서로 데이터와 신호를 주고 받는 통로
- 주소 버스(주소) + 데이터 버스(명령어+데이터) + 제어 버스(제어 신호)
메인보드 밖
- 보조기억장치
- 비휘발성 저장장치
- 입출력장치
- 보조기억장치를 제외한 외부 장치
컴퓨터의 데이터 단위
- 비트 : 0 or 1 (2진법)
- 2진수에서 음수를 구하는법
- 2진수의 0과 1을 반전 시킨다. ( 1011 ➡️ 0100)
- 1을 더해준다 (0100 ➡️ 0101)
- 플래그 레지스터를 On 시켜준다.
- 2진수에서 음수를 구하는법
- n비트 ➡️ 2^n 가지의 정보 표현 가능
- 워드 : CPU가 한 번에 처리할 수 있는 크기
- 하프 워드 : 워드의 절반
- 풀 워드 (= 워드)
- 더블 워드 : 워드의 2배
- Ex) 32bit cpu의 1word는 32bit
- 문자 집합 : 컴퓨터가 이해할 수 있는 문자들
- 인코딩 : 문자들을 이진수로 코드화하는 과정
- 디코딩 : 이진수로 이루어진 바이너리 코드를 문자로 변환하는 과정
- 아스키 코드
- 8비트(7비트의 문자와 1비트의 패리티 비트)로 표현 가능한 문자 집합
- 장점 : 간단한 인코딩
- 단점 : 다양한 언어 문자, 특수 문자 표현 불가
- 완성형 인코딩 : 완성된 한글 한 문자에 대해 코드를 부여
- EUC - KR
- 약 2바이트(16비트) 정도 사용
- 모든 한글을 표현할 수 없다. (약 2300개 정도의 한글만 표현 가능)
- 문제점 : 각 언어별로 완성형 인코딩을 적용할 경우, 코드의 수가 과도하게 많아진다. ➡️ 유니코드 utf의 등장배경
- 조합형 인코딩 : 초성, 중성, 종성에 대해 코드를 부여 후 조합
- 유니코드와 UFT
- 모든 언어(한글, 영어, 중국어 등), 특수문자(화살표, 이모티콘 등)에 대해 통일된 문자 집합(유니코드)과 인코딩 방식(UTF)
- UTF-8, UTF-16, UTF-32 ? : 유니코드의 인코딩 방식
- 유니코드 코드 포인트 : 각 문자들이 가진 고유한 16진수 코드. 이 코드를 UTF-8, UTF-16 등 다양한 방식으로 인코딩한다.
- UTF(Unicode Transformation Format)-8
- 대표적인 유니코드 인코딩 방식
- 가변 길이 인코딩 : 인코딩 결과는 1~4 바이트를 가지는 데, 몇 바이트가 될지는 유니코드 코드 포인트에 따라 달라진다.
저급 언어 ↔️ 고급 언어
저급 언어 (Low Level)
- 기계어 : 0과 1로 이루어진 언어
- 어셈블리어 : 기계어를 사람이 보기 좋은 방식으로 변환한 언어
고급 언어 (High Level)
- 컴파일 언어
- 고급 언어(소스 코드) ➡️ 컴파일 ➡️ 저급 언어(목적 코드)
- 코드 중간에 오류가 있다면, 컴파일 에러
- 목적 코드의 종류는 컴파일러에 따라 달라진다.
- 인터프리터 언어
- 인터프리터에 의해 한 줄씩 실행
- 장점 : 소스 코드 전체가 저급 언어로 변환되기(컴파일 과정)를 기다릴 필요 ❌
- 코드 중간에 오류가 있어도, 해당 오류 코드를 만나기 전까지는 실행
명령어 구조
OP Code | Operand |
명령어 = 1개의 연산 코드(op code) + 0~3개의 주소 필드(operand)
ex) push rbp / mov rbp, rsp / add eax, edx ...
- 연산 코드(opcode) : 저장해라, 빼라, 더해라 같은 연산에 대한 코드
- 연산코드는 CPU마다 다르다.
- 데이터 전송 코드 : 데이터 저장, 이동에 관한 명령어
- MOVE, STORE, LOAD, PUSH, POP 등...
- 산술/논리 연산 : 산술, 논리 연산에 관한 명령어
- ADD / SUBTRACT / MULTIPLY / DIVDE / INCREMENT / DECREMENT / AND / OR / NOT / COMPARE 등
- 제어 흐름 변경 : PC(Program Counter)의 이동 및 흐름에 관한 명령어
- JUMP / CONDITIONAL JUMP / HALT / CALL / RETURN ...
- 입출력 제어 : 데이터의 입출력에 관한 명령어
- READ / WRITE / START IO / TEST IO ...
- 데이터 전송 코드 : 데이터 저장, 이동에 관한 명령어
- 주소필드(operand) : 연산에 사용될 데이터 혹은 데이터의 위치(레지스터 주소 / 메모리 주소)
- 유효 주소 (Effective Address) : 데이터가 저장된 위치
- 명령어 주소 지정 방식 (Addressing Modes) : 유효 주소를 찾거나 다양한 명령어 주소를 지정하는 방식
- 아래 단계별로 발전
- 즉시 주소 지정 방식 (Immediate Addressing Mode)
- 오퍼랜드에 데이터의 주소가 아닌, 데이터 자체를 직접 명시
- 가장 간단한 방식
- 장점 : 빠름
- 단점 : 연산에 사용할 데이터의 크기가 제한
- 직접 주소 지정 방식 (Direct Addressing Mode)
- 오퍼랜드에 유효 주소를 직접 명시,
- 오러팬드의 유효 주소 ➡️ 데이터
- 장점 : Immediate Addressing Mode 보다 큰 데이터를 사용 가능.
- 단점 : 유효 주소를 표현할 수 있는 크기가 제한
- 간접 주소 지정 방식 (Indirect Addressing Mode)
- 오퍼랜드에 유효 주소의 주소를 명시
- 장점 : Direct Addressing Mode보다 더 많은 데이터 주소를 사용가능
- 단점 : 느리다. (오퍼랜드의 간접 주소 ➡️ 유효 주소 ➡️ 데이터, 3단계를 거쳐 데이터에 진입하므로 느림)
- 레지스터 주소 지정 방식 (Register Addressing Mdoe)
- 사용할 데이터가 저장된 레지스터 주소를 오퍼랜드에 명시
- 장점 : 빠르다. (레지스터를 이용하기 때문에)
- 레지스터 간접 주소 지정 방식 (Register Indirect Addressing Mode)
- 간접 주소 지정 방식 + 레지스터 주소 지정 방식
- 유효 주소를 저장한 레지스터의 주소를 오퍼랜드에 명시
- 즉시 주소 지정 방식 (Immediate Addressing Mode)
컴파일의 과정
- 전처리 Preprocess
- ~.c ➡️ ~.i
- 선언된 소스 코드, 라이브러리 불러옴 (#include)
- 매크로 변환 (#define)
- 컴파일 영역 표시 (#if / #ifdef, ...)
- 컴파일 Compile
- ~.i ➡️ ~.s
- 전처리된 파일을 어셈블리어로 변환
- 어셈블링 Assembling
- ~.s ➡️ ~.o (목적코드 파일)
- 어셈블리어를 기계어로 변환
- 링킹 Linkiing
- ~.o ➡️ ~.exe (실행 파일)
- 각 목적파일(~.o)들을 연결시킴
명령어 사이클 , 인터럽트
명령어 사이클
- Fetch (인출 사이클)
- 메모리 ➡️ ( 명령어 ) ➡️ 명령어 레지스터
- Decode (해석 사이클)
- 가져온 명령어를 해석
- Excuete ( 실행 사이클)
- 해석한 명령어를 실행
- Store (저장 사이클)
- 실행한 명령어의 결과 메모리 혹은 레지스터에 저장
인터럽트
- 1~3번 과정 사이에서 인터럽트가 발생할 수 있음
- 해당 흐름을 잠시 중단 후, 다른 작업을 먼저 처리
1. 동기 인터럽트 (예외)
- CPU가 예기치 못한 예외 상황에서 발생
2. 비동기 인터럽트 (하드웨어 인터럽트)
- 마우스, 모니터 등 입출력 장치에 의해 발생
- 인터럽트의 과정
- I/O 장치 ➡️ (인터럽트 요청 신호) ➡️ CPU (인출 사이클 진입 전 항상 인터럽트 요청 여부 확인)
- 인터럽트 요청이 있으면, CPU는 인터럽트 플래그를 확인해 인터럽트 가능 여부 확인
- 인터럽트가 가능하면, CPU는 현재까지의 작업을 백업(메모리의 스택영역에 저장)
- CPU는 인터럽트 벡터를 참조해, 인터럽트 서비스 루틴을 실행
- 인터럽트 서비스 루틴 종료 후, 백업해둔 작업을 불러와 다시 실행
인터럽트 서비스 루틴 (드라이버)
메모리에 저장된 각각의 인터럽트 상황에 대한 프로그램.
인터럽트 서비스 루틴 = 주변 장치를 컴퓨터와 연결하면 설치되는 드라이버의 IRQ(interrupt request).
ex) 마우스 / 키보드 동작 ➡️ (인터럽트 요청 신호 + 인터럽트 벡터) ➡️그에 맞는 인터럽트 서비스 루틴 (마우스 / 키보드의 드라이버) .
모니터 동작 ➡️ (인터럽트 요청 신호 + 인터럽트 벡터) ➡️그에 맞는 인터럽트 서비스 루틴 .
인터럽트 벡터
각각의 인터럽트 서비스 루틴의 시작점을 구분하기 위한 정보.
메모리의 인터럽트 벡터 테이블 내에 저장되어 있음.
CPU 설계
클럭
- CPU의 동작 신호에 대한 전기 신호.
- 1초에 클럭이 반복되는 횟수를 Hz단위로 측정(100Hz = 1초에 100번의 클럭 발생)
- Hz가 높을 수록 더 많은 전기 신호를 보내고, 그 만큼 작업을 수행
클럭 속도를 늘리는 방법
1. CPU의 코어 수 늘리기
코어
- CPU의 본체, 즉, ALU, 제어장치, 레지스터를 독립적으로 가지고 작업을 수행하는 부품
- Ex) 코어가 2개이면, 독립적인 CPU가 2개
2. 스레드(Thread) 수 늘리기
- 하드웨어적 스레드(논리 프로세서): 하나의 코어가 동시에 처리하는 명령어 단위
- Ex) 2코어 4스레드의 멀티 스레드 CPU : 2개의 코어가 각각 2개씩 총 4개의 명령어를 수행.
- 각 코어에 독립적인 레지스터 세트를 달아줘야함.
- 각 코어가 2개의 레지스터 세트를 가지면, 클럭이 1번 발생될 때, A코어의 A레지스터 세트와 B레지스터 세트가 1번씩 동작하게 된다.
- 소프트웨어적 스레드 : 하나의 프로그램에서 독립적으로 실행되는 단위
- Ex) 어떤 워드 프로그램에 "내용 출력", "검사 기능", "내용 저장"을 동시에 작동되어야 할 때, 각 기능에 대한 스레드를 소프트웨어적으로 구현
명령어 파이프 라인(명령어 병렬처리)
위에 작성한 명령어 사이클(인출, 해석, 실행, 저장)의 단계가 겹치지않는다면 CPU는 각 단계를 동시에 실행 할 수 있음.
- Ex) 처리해야할 A명령어, B명령어, C명령어가 있을 때,
가능) A명령어의 인출 + B명령어의 해석 + C명령어의 실행
불가능) A명령어의 인출 + B명령어의 인출(같은 인출 단계로 겹침) +C명령어의 실행
t0 | t1 | t2 | t3 | t4 | t5 | |
A명령어 | 인출 | 해석 | 실행 | 저장 | ||
B명령어 | 인출 | 해석 | 실행 | 저장 | ||
C명령어 | 인출 | 해석 | 실행 | 저장 | ||
D명령어 | 인출 | 해석 | 실행 | |||
... | ||||||
... |
하지만, 파이프 라인이 정상적으로 동작하지 않을 수 있는 파이프 라인 위험(pipeline hazard)이 존재한다.
- 데이터 위험 : 명령어 간의 의존성에 의해 발생 ( 명령어 간 실행 순서를 지켜야할 경우) ➡️ 비순차적 명령어 처리(OoOE)로 극복
- 예를 들어, 아래와 같은 2개의 명령어를 파이프 라인으로 실행할 경우,
"명령어 1 : R1 ⬅️ R2 + R3 "
"명령어 2 : R2 ⬅️ R1 + R5 "
"명령어 2"가 실행되기 위해서, "명령어 1"이 실행되어야 하기 때문에 각 명령어를 병렬적으로 처리 불가능.
- 예를 들어, 아래와 같은 2개의 명령어를 파이프 라인으로 실행할 경우,
- 제어 위험 : PC의 갑작스런 변화에 의해 발생 (JUMP, Interupt 등...) ➡️ 분기 예측(Branch Prediction)으로 극복
- 예를 들어, 아래와 같은 2개의 명령어가 있을 때,
"명령어 1 : Jump 60 (60번지로 이동)"
"명령어 2 : 인출 사이클"
명령어 1의 60번지 분기 이동 실행에 의해 PC가 바뀌게 되어, 명령어 2는 가져올 명령어 주소를 알 수 없게 되어 인출 과정이 불가능해진다. - 분기 예측 Branch Prediction
- CPU가 분기 명령어(JUMP, JUMP IF, CALL 등)를 미리 예측하여, 다음 명령어를 미리 가져옴
예측이 맞음 ➡️ 다음 명령어를 가져옴
예측이 틀림 ➡️ 예측된 명령어 버리고, 분기 명령어 이후의 올바른 명령어를 가져옴 (Bubble이 발생할 수도 있음) - 파이프라인 버블(bubble) : 현재의 명령어 실행을 잠시 중단 ➡️ 성능 저하
- CPU가 분기 명령어(JUMP, JUMP IF, CALL 등)를 미리 예측하여, 다음 명령어를 미리 가져옴
- 예를 들어, 아래와 같은 2개의 명령어가 있을 때,
- 구조적 위험 : 서로 다른 명령어가 같은 같은 CPU 부품(ALU, 레지스터 등)을 사용할 때 발생
슈퍼스칼라
CPU 내부에 여러 개의 명령어 파이프라인을 포함하는 구조.
- 반드시, 파이프 라인의 개수에 비례하여 처리 속도가 증가하지는 않는다.
- 파이프 라인의 수가 늘어날 수록, 관리해야할 파이프 라인이 늘어나고, 그 만큼 파이프 라인 위험(Pipeline Harzard)이 자주 발생할 수 있기 때문에...
비순차적 명령어 처리(OoOE) (영상의 3시간 58분 보는걸 추천)
파이프라인 중단을 막기 위해, 명령어를 순차적으로 실행 ❌, 효율적으로 순서를 변형
예를 들어, 아래와 같은 상황이 있을 때,
line 1 : M (100) ⬅️ 1
line 2 : M (101) ⬅️ 2
line 3 : M (102) ⬅️ M(100) + M(101)
❌ line 3이 실행되기 위해선, Line 1과 Line 2가 실행 완료 후 저장되어야한다. 하지만, Line3 시점에서 Line1과 Line2는 실행 사이클 이하의 과정이기 때문에 파이프라인의 데이터 위험이 발생❌
line 4 : M (150) ⬅️ 1
line 5 : M (151) ⬅️ 2
line 6 : M (152) ⬅️ 3
아래와 같이 효율적으로 명령어의 순서를 바꿈
line 1 : M (100) ⬅️ 1
line 2 : M (101) ⬅️ 2
line 4 : M (150) ⬅️ 1
line 5 : M (151) ⬅️ 2
line 6 : M (152) ⬅️ 3
line 3 : M (102) ⬅️ M(100) + M(101)
명령어 집합 구조
명령어 집합 구조(ISA, Instruction Set Architecture) : CPU가 이해할 수 있는 명령어들의 모음(CPU의 언어)
Ex) 인텔은 X86 명령어 집합을 따르고, 애플은 ARM 명령어 집합을 따름.
x86(CISC) | ARM(RISC) | |
저장/로드 | mov eax, 5 | ldr r0, 5 |
연산 | add ebx, ecx | add r0, r1, r2 |
점프 | jmp label | b label |
CISC (Complex instruction Set Computer)
복잡한 명령어 집합을 활용하는 CPU (x86, x86-64 등)
- 복잡하고 다양한 명령어 활용 ➡️ 적은 수의 명령어로 실행 가능 !
- 명령어의 형태와 크기가 가변적임 (가변 길이 명령어)
- 장점
- 적은 메모리로도 동작 가능 ➡️ 메모리 절약
- 단점
- 명령어 파이프라이닝에 불리함. (명령어 파이프라이닝은 명령어의 실행 주기가 정형화되어야 유리하다.)
- 왜? 명령어가 복잡하고 다양한 기능을 제공(가변적)
다양한 기능(가변성) ➡️ 명령어의 크기와 실행까지의 시간이 일정❌
복잡한 명령어 ➡️ 명령어 하나를 실행하는 데 여러 클럭 주기가 필요
- 왜? 명령어가 복잡하고 다양한 기능을 제공(가변적)
- 다양하고 복잡한 기능은 제공하지만, 대부분 소수의 명령어만 사용. (자주쓰는 것만 씀)
- 명령어 파이프라이닝에 불리함. (명령어 파이프라이닝은 명령어의 실행 주기가 정형화되어야 유리하다.)
- (명령어 파이프라이닝의 이점을 챙기기 위해, 요즘 CISC들은 RISC처럼 동작)
RISC (Reduced Instruction Set Computer)
종류가 적고, 짧고, 규격화된(고정된 길이) 명령어를 사용하는 CPU (ARM)
- 메모리 접근을 최소화 (읽기 / 쓰기)
- 레지스터를 최대한 활용
- 장점
- 간단하다.
- 고정된 길이를 가진다 ➡️ 명령어 파이프라이닝에 유리
- 단점
- CISC보다 많이 메모리 사용
정리
CISC | RISC |
복잡, 다양 | 단순, 적음 |
가변적 | 고정적 |
다양한 주소 지정 방식 | 적은 주소 지정 방식 |
명령어 길이 짧음 (명령어의 줄 수 짧음) | 명령어 길이가 길다 (명령어의 줄 수 김) |
여러 클럭에 걸쳐 수행 | 1클럭 내외로 수행 |
파이프라이닝 불리 | 파이프라이닝 유리 |
RAM (2023.04.25)
DRAM ( Dynamic(동적) RAM )
- 일반적 많이 사용되는 RAM(주기억장치)
- 저장된 데이터가 동적인 RAM ➡️ 데이터가 사라진다.
- 데이터의 소멸을 막기 위해 주기적으로 재활성화해야 한다.
- 장점
- 상대적으로 소비 전력이 낮음
- 저렴함
- 집적도가 높음 ➡️ 대용량 설계에 용이
SRAM ( Static(정적) RAM )
- 저장된 데이터가 정적인 RAM ➡️ 데이터가 사라지지 않는다.
- 일반적으로 캐시 메모리로 사용
- 장점
- DRAM보다 빠르다.
- 단점
- 소비전력이 높음
- 가격이 비쌈
- 직접도가 낮음 ➡️ 대용량으로 설계 불리 ➡️ 큰 용량이 필요없고, 속도가 중요한 장치(캐시)에 사용
SDR SDRAM (Single Data Rate Synchronous DRAM )
- DRAM의 발전된 형태의 RAM으로 DRAM과 유사
- 클럭 신호와 동기화되어 있음
- DRAM + 클럭 신호와 동기화 ➡️ SDRAM
DDR SDRAM ( Double Data Rate SDRAM)
- SDRAM이 발전한 형태
- 최근 가장 대중적으로 사용하는 RAM
- SDRAM에서 대역폭을 넓혀 속도를 빠르게 만듬 (SDRAM의 2배)
- SDRAM + 대역폭 넓게(한번에 더 많은 데이터 ➡️ 전송 속도 증가) ➡️ DDR SDRAM
- 이후, DDR2, DDR3로 발전.
- DDR2 : DDR의 2배 넓은 대역폭
- DDR3 : DDR의 4배 넓은 대역폭
- DDR(n) ➡️ SDR SDRAM의 대역폭의 2^n배
메모리의 주소
메모리의 상태(저장된 값들)는 시시각각 변화 ➡️ CPU는 어디에 어떤 데이터가 적재되어 있는지 알 수 없다. ➡️ 논리 주소와 물리 주소의 등장
물리 주소
- 메모리 관점의 하드웨어 상의 실제 주소
논리 주소
- CPU가 이해하는 주소체계
- CPU와 실행 중인 프로그램 관점에서의 실행중인 프로그램에 부여된 주소 (0번지부터 시작)
- 각 프로그램의 시작점(0번지)으로부터 얼마나 떨어져 있는지를 저장
CPU가 메모리와 상호작용하기 위해선 논리 주소를 물리 주소로 변환하는 과정이 필요
- 왜?
- 논리 주소는 개별 프로그램마다 0번지부터 시작 ➡️ 논리 주소상에는 0번지가 여러개 일 수 있음
- 물리 주소는 0번지가 단 하나만 존재
- 결국, CPU가 메모리를 사용하기 위해선, 데이터가 저장된 실제 주소(물리 주소)가 필요. (MMU가 처리)
MMU (Memory Management Unit) 메모리 관리 장치
- CPU가 메모리를 이용할 수 있도록, 논리 주소를 물리 주소로 변환해주는 장치.
- 논리 주소(현재 프로그램 시작점부터의 거리) + 베이스 레지스터(프로그램의 물리 주소 시작점) ➡️ 물리 주소
메모리 보호
- 한계 레지스터
- 프로그램의 영역을 침범할 수 있는 명령어의 실행을 막음
- 논리 주소의 최대 크기를 저장 (프로그램의 끝점)
- CPU는 프로그램의 한계 레지스터를 벗어난 논리 주소에 접근할 수 없음.
캐시 메모리
- 기반
- 저장장치는 CPU와 가까울수록 빠르다.
- 레지스터 : 가장 가까움 ➡️ 가장 빠름
RAM (주 기억장치 ) : 레지스터와 USB의 중간
USB (보조 기억장치) : 가장 느림
- CPU와 메모리 사이에 위치한 메모리.
- CPU ➡️ 레지스터 ➡️ L1캐시 ➡️ L2캐시 ➡️ L3캐시 ➡️ 주기억장치 ➡️ 보조기억장치
(➡️ 레지스터보다 용량이 크고, 메모리보다 빠른 SRAM 저장 장치)
- CPU ➡️ 레지스터 ➡️ L1캐시 ➡️ L2캐시 ➡️ L3캐시 ➡️ 주기억장치 ➡️ 보조기억장치
- CPU의 연산 속도 ↔️ 메모리 접근 속도 차이를 줄이기 위해 등장
- CPU에서 사용할 데이터의 일부를 미리 가져와 저장
캐시 메모리의 계층
CPU의 코어 내부에 위치
- L1 : 가장 빠르고, 작은 캐시 메모리
- L2 : L1과 L3 중간
CPU ↔️ 메모리 사이 위치
- L3 : 가장 느리고, 큰 캐시 메모리
분리형 캐시
캐시를 더 빠르게 만들기 위해, L1을 분리한 형태 (L1 ➡️ L1D, L1I 로 분리)
왜 분리? ➡️ 캐시 내부에 데이터와 명령어의 위치가 분리되어, CPU가 척척 찾을 수 있음
- L1D (Level 1 Data): L1의 데이터 캐시
- 변수, 배열 등 자주 사용하는 데이터를 저장할 때 사용
- L1I (Level 1 Instruction) : 명령어 캐시
- CPU가 실행할 명령어를 읽을 때 사용
참조 지역성 원리
- CPU는 최근에 접근했던 메모리 공간에 다시 접근하려는 경향이 있다.
- CPU는 접근한 메모리 공간 근처를 접근하려는 경향이 있다. ( For 문, 배열 등...)
- 위의 두 가지 참조 지역성을 반영하여, 사용할 데이터를 미리 캐시에 저장한다.
- 캐시 메모리에는 CPU가 사용할 데이터를 잘 예상해서 적재해야한다. 잘 예상하는 방법 중 하나가 데이터의 참조 지역성을 이용하는 것!
- Cache Hit : 잘 예상해서 CPU가 사용 ➡️ 성능 상승
Cache Miss : 예상 실패해서 CPU가 사용 안함 ➡️ 성능 하락
보조기억장치 (2023.04.28)
1. 하드 디스크
자기적인 방식으로 데이터를 저장하는 보조기억장치로, 플래터(Platter) 표면에 코딩된 자성체에 데이터가 기록이 된다.
- 보통 플래터(Platter)는 양면을 모두 사용!
- RPM : 분당 회전수, 스핀들(Spindle)이 플래터(Platter)을 1분에 몇 바퀴를 돌리는지에 대한 지표.
하드디스크 각 구성요소의 역할
- 플래터(Platter) : 데이터가 저장되는 원판.
- 스핀들(Spindle) : 플래터(Platter)를 회전시켜주는 장치.
- 헤드(Head) : 플레터에 데이터를 기록하거나, 읽는 장치(보통 플래터 각면마다 존재)
- 액추에이터 암(Actuator Arm) : 헤드의 몸체. ("헤드 암"이라고도 부른다.)
하드 디스크의 저장
- 트랙 섹터(C)들의 모든 집합이 트랙(A)이다.
- 섹터의 크기는 512Byte ~ 4096Byte
하드디스크는 여려 겹의 플래터와 액츄에이터로 구성되어 있는데, 데이터가 읽거나 쓸 때, 액츄에이터들 같이 움직이며, 플래터에 데이터를 읽거나 저장한다. 즉, R/W 과정에서 각 헤더들은 각층의 플래터에서 동일한 XY축의 트랙에 접근해 데이터를 읽거나 쓴다. 따라서, 각 층의 플래터의 각 트랙은 함께 동작되는 데, 이 트랙들을 논리적 단위로 묶어 "실린더"라고 부르고, 데이터는 실린더단위로 읽거나 기록된다.
하드디스크의 접근 시간
하드 디스크의 접근 시간 = 탐색 시간(Seek Time) + 회전 지연(Rotational Latency) + 전송 시간(Transfer Time) 총 3개의 시간의 합.
- 탐색 시간(Seek Time) : 헤더가 데이터가 저장된 플래터의 트랙층(섹션 아님!)으로 이동하는 데 걸리는 시간.
- 회전 지연(Rotational Latency) : 헤드 위치로 플래터를 회전하는데 걸리는 시간.
- 전송 시간(Transfer Time) : 하드 디스크↔️컴퓨터 간, 데이터를 전송하는 데 소요되는 시간
2. 플래시 메모리
전기적으로 데이터를 읽고 쓰는 반도체 저장 장치.
- 보조기억 장치 외에 주기억장치 ROM으로도 사용되는 범용성이 높은 저장 장치.
종류
- NAND 플래시 메모리
- 현대에 가장 많이 사용하는 방식
- NAND 게이트를 기반
- 덮어쓰기 불가능
- NOR 플래시 메모리
- NOR 게이트를 기반.
NAND 플래시 메모리
종류
- SLC (SIngle Level Cell): 한 셀당 1비트 저장
- 한 셀에 1비트 ➡️ "0", "1" 총 2개(2^1)의 정보 표현 가능
- 비트의 빠른 입출력
- 긴 수명
- 용량에 비해 비쌈 ➡️ 보편적으로 사용되지 않음.
- MLC (Multi Level Cell): 한 셀당 2비트 저장
- 한 셀에 2비트 ➡️ "00", "01", "10", "11" 총 4(2^2)개의 정보 표현 가능
- (SLC 대비) 느린 입출력
- (SLC 대비) 짧은 수명
- (SLC 대비) 저렴 ➡️ 많이 사용된다.
- TLC (Triple Level Cell): 한 셀당 3비트 저장
- 한셀에 3비트 ➡️ 8(2^3)개의 정보 표현 가능
- (MLC 대비) 느린 입출력
- (MLC 대비) 짧은 수명
- (MLC 대비) 저렴 ➡️ 많이 사용된다.
- QLC (Quadruple Level Cell): 한 셀당 4비트 저장
저장 단위 (NAND 플래시 기준)
Cell ➡️ Page ➡️ Block ➡️ Plane ➡️ Die
- 셀 Cell : 플래시 메모리에서 데이터를 저장하는 가장 작은 단위
- 페이지 Page: 셀들의 집합 (읽기/쓰기 단위)
- 페이지 상태
- Free 상태 : 비어 있는 상태 ➡️ 새로운 데이터 저장 가능
- Valid 상태 : 유효한 데이터가 저장된 상태
- Invalid 상태 : 유효하지 않는 데이터가 저장된 상태
덮어쓰기가 불가능해, 기존의 값이 수정되면 기존 값을 가진 Page는 Invalid 상태가 되고, 수정된 데이터를 저장하는 Valid한 페이지가 생성된다.
이후, Garbage 컬렉터가 Invalid 페이지를 정리
- 페이지 상태
- 블록 Block : 페이지들의 집합 (삭제 단위)
- 플레인 Plane : 블록의 집합
- 다이 Die : 플레인의 집합
RAID(2023.04.29)
Redundant Array of Independent Disks : 여러 개의 독립적인 디스크들을 하나로 모아 논리적 보조기억장치처럼 사용하는 기술 ➡️ 4개의 디스크를 RAID로 묶어서 사용하면, 묶인 용량만큼의 단일 디스크보다 성능과 안전성이 높아진다.
- RAID 레벨마다 장단점이 있음.
- 보통 RAID 레벨이 높아질수록, 안전성은 높아지고⬆️, 속도는 낮아짐⬇️
- 빠른 입출력이 필요 ➡️ 낮은 레벨
- 높은 안전성이 필요 ➡️ 높은 레벨
RAID 0
- 묶여진 각 하드디스크를 순차적으로 돌아가며, 데이터를 저장. (1번째 디스크에 데이터 저장 ➡️ 2번 째 디스크에 데이터 저장 ➡️ ... ➡️ 4번째 디스크에 데이터 저장 ➡️ 다시 1번째 디시크에 데이터 저장)
- 스트라입 (Stripe) : 아래 그림과 같이 각 디스크에 A1, A3 ... A7처럼 줄무늬 형태로 분산되어 저장되는데, 이러한 각 디스크의 층이 줄무늬처럼 생겨 스트라입이라고 한다.
- 장점
- 입출력 속도 향상 : 각 디스크의 데이터를 동시 참조 가능 (A1, A2를 참조)
- 단점
- 저장된 정보가 불안전 : 디스크가 하나라도 고장나면, 사용 불가
Raid 1
- 미러링 (Mirroring) : RAID 0의 복사본을 만드는 방식 ( 데이터를 쓸 때, 원본과 복사본 두 군데에 저장 ➡️ 느리다)
예를 들어, RAID 0에서 4개의 디스크를 묶어서 사용했다면, RAID 1에서는 2개의 디스크를 묶어서 RAID를 구성 후, 남은 2개의 디스크는 구성한 RAID의 복사본으로 사용! - 장점
- 백업과 복구가 수월하다. ( 복사본을 바로바로 만드니까) ➡️ RAID 0에 비해 안전성 향상
- 단점
- RAID 0에 비해 느림.
왜? 같은 데이터를 쓰더라도, 원본과 복사본 두 곳에 데이터를 써야하니까 - 용량이 적어짐(절반은 복사본으로 사용하니까) ➡️ 비용 증가
- RAID 0에 비해 느림.
RAID 3 / RAID 4
- RAID 1처럼 완전 복사본을 만들지 않고, 일부 디스크에 오류를 검출하고 복구하기 위한 정보(패리티 비트)를 저장
(원래 패리티 비트는 컴퓨터 공학적으로, 오류 복구용 정보가 아닌 오류 검출용 비트지만,
RAID 3/4에서는 오류 검출용+오류 복구용의 역할을 수행한다.) - RAID 3 ↔️ RAID 4 차이
- RAID 3 : 데이터들이 바이트(Byte) 단위로 쪼개어져 저장됨.
- RAID 4 : 데이터들이 블록(Block) 단위로 쪼개어져 저장됨.
- 장점
- RAID 1보다 용량이 큼. (안전성은 유지하고, 용량은 증가)
- 단점
- 패리티 비트를 저장하는 패리티 디스크에 병목 현상이 일어날 수 있음
예를 들어, 4개의 하드디스크(A디스크 ~ D디스크)를 사용할 때, D디스크를 패리티 디스크로 사용할 경우, A~C 디스크에 대한 패리티 비트를 D디스크에 모두 저장한다. 따라서, A~C 디스크에 데이터의 읽기/저장 과정에서 동시에 D디스크를 사용하게 되어 병목 현상이 발생!
- 패리티 비트를 저장하는 패리티 디스크에 병목 현상이 일어날 수 있음
RAID 5
- 각각의 디스크가 패리티 정보를 분산하여 저장.
(RAID 3/4는 한 디스크에 몰아서 패리티 비트를 저장한 반면, RAID 5는 모든 디스크들이 자신의 일부 스트라입에 패리티를 나누어서 저장한다. 이때, 자기 자신의 패리티 비트는 저장 불가능(A디스크면 B,C,D 디스크 중 하나의 패리티 비트를 저장!))
RAID 6
- RAID 5의 각 디스크의 패리티 정보 스프라입을 추가로 저장.
- RAID 5에서는 각 디스크는 하나의 스트라입에 다른 한 디스크의 패리티 정보를 저장했지만, RAID 6는 2개 이상의 스트라입에 두 개이상의 다른 디스크의 패리티 정보를 저장한다.
- 장점
- RAID 5보다는 안전 (한 디스크에서 2개의 디스크의 패리티 정보를 저장 하니까)
- 단점
- RAID 5보다는 느리다.
입출력 장치 - I/O 장치 (2023.04.30)
- 입출력 장치의 특징
- 입출력 장치의 종류는 매우 다양하다 ➡️ 속도, 데이터 전송 형식 등이 제각각 ➡️ 규격화하기가 어렵다.
- 입출력 장치의 데이터 전송률은 낮다. (CPU ↔️ 메모리의 데이터 전송률은 높다.)
- 입출력 장치의 통로
- 하드웨어적 통로 = 장치 컨트롤러
- 소프트웨어적 통로 = 장치 드라이버
장치 컨트롤러 (하드웨어)
위 입출력 장치 특징에서 발생하는 한계점을 극복하기 위한 장치이다. 이 장치 컨트롤러를 통해 I/O 장치와 컴퓨터가 연결이 된다.
- 시스템 버스 ↔️ 장치컨트롤러 ↔️ I/O 장치
장치 컨트롤러의 역할
- CPU ↔️ I/O 통신 중개 (제각각의 I/O 장치들을 어느정도 규격화)
- 오류 검출
- 데이터 버퍼링 (버퍼를 이용해 낮은 데이터 전송률을 어느정도 극복 )
장치 컨트롤러의 구성요소
장치 컨트롤러 = 데이터 레지스터 + 상태 레지스터 + 제어 레지스터
- 데이터 레지스터 : 전송할 데이터 저장
- CPU ↔️ [데이터] ↔️입출력 장치, 주고받을데이터 저장하는 장치
- RAM을 사용하기도 한다.
- 상태 레지스터 : IO장치 상태 저장
- I/O 장치가 입출력 작업할 준비가 되었는지 상태 저장
- I/O 작업이 완료가 되었는지 상태 저장
- I/O 장치에 오류가 없는지 상태 저장
- 제어 레지스터 : 제어 정보 저장
- 입출력장치가 수행할 내용에 대한 제어 정보 저장
- ❇️ 상태 레지스터와 제어 레지스터는 하나의 레지스터로 합쳐서 사용하기도 한다.
장치 드라이버 (소프트웨어)
운영체제가 장치 컨트롤러의 동작을 감지하고 제어하는 프로그램.
- 마우스, 모니터 등 각각의 I/O 장치에 맞는 장치 드라이버를 설치해야한다.
입출력 방식 3가지
- 프로그램 입출력
- 인터럽트 입출력
- DMA 입출력
1. 프로그램 입출력
프로그램 속 명령어로 입출력장치를 제어 (= CPU가 장치 컨트롤러의 레지스터 값을 읽고 씀)
- 명령어 ➡️ 장치 컨트롤러 ➡️ I/O 장치 제어
- 예) 하드디스크에 새로운 데이터 저장 과정 (강의 영상 6시 16분 부분 참고 추천)
- CPU ➡️ 쓰기 명령어 ➡️ 하드 디스크 장치 컨트롤러의 제어 레지스터에 제어 정보 저장
- 하드디스크 장치 컨트롤러가 하드 디스크 상태 확인 ➡️ 상태 레지스터에 준비 완료 표시
- CPU가 상태 레지스터를 확인 (작업 할 준비가 되었는지)
- 작업할 상태가 준비되면, CPU가 하드디스크에 저장할 데이터를 데이터 레지스터에 저장
- CPU가 연결된 각 장치 컨트롤러들의 레지스터 주소를 어떻게 알까? ➡️ 메모리 맵 입출력 방식 | 고립형 입출력 방식
- 메모리 맵 입출력 방식 (Memory-mapped I/O, MMIO)
- 메모리의 특정 공간에 입출력 장치에 접근하기 위한 주소들을 저장 (예를 들어, 메모리의 0~512 번지는 메모리용 주소 공간, 나머지 512~1023 번지는 I/O 장치용 주소 공간으로 사용)
- 메모리의 주소 공간 = 메모리를 위한 주소 공간(메모리 주소) ➕입출력 장치를 위한 주소 공간(I/O 장치 컨트롤러의 레지스터 주소)
- 고립형 입출력 방식 (Isolated I/O , Port Mapped I/O)
- MMIO처럼 메모리 공간을 분리하지 않고, 명령어를 구분하여 사용하는 방식
➡️CPU가 명령어만 봐도, I/O 장치 컨트롤러에 대한 명령어인지 구분 가능!
- 예) Port Mapped I/O
(메모리) MOV / LD ↔️ (입출력) IN / OUT
- 예) Port Mapped I/O
- 입출력 전용 명령어를 사용 ‼️
- MMIO처럼 메모리 공간을 분리하지 않고, 명령어를 구분하여 사용하는 방식
- MMIO ↔️ Isolated I/O 비교
- 메모리 맵 입출력 방식 (Memory-mapped I/O, MMIO)
메모리 맵 입출력 (MMIO) | 고립형 입출력 (Isolated I/O) | |
주소 분리 | X (메모리 안에서 같이 사용) | O |
I/O 전용 명령어 | X(메모리 주소 명령어 = I/O 주소 명령어) | O |
2. 인터럽트 입출력 (2023.05.03)
장치 컨트롤러가 하드웨어 인터럽트를 발생시켜, 입출력 진행
- CPU ➡️ (입출력 명령) ➡️ 장치 컨트롤러
- 장치 컨트롤러 ➡️ (인터럽트 요청) ➡️ CPU
- 프로그램 입출력 방식에서는 CPU가 하드웨어의 장치 컨트롤러 내 상태 레지스터를 주기적으로 확인.
반면, 인터럽트 입출력 방식은 하드웨어의 장치 컨트롤러가 인터럽트 요청을 할 때, 입출력이 진행 - 각 I/O 장치의 인터럽트는 동시다발적으로 들어올 수 있다. 만약, 인터럽트가 동시다발적으로 발생한다면 어떻게 처리해야할까? 아래는 동시다발적인 인터럽트의 처리 기준이다.
- 우선순위
- PIC (Programmable Intrrupt Controller)를 사용
- PIC란 ?
- 여러 장치 컨트롤에 연결되어, 각 장치 컨트롤러의 하드웨어 인터럽트의 우선순위를 판단.
(이때, NMI는 제외하고 동작한다.) - CPU에게 지금 처리해야하는 인터럽트가 무엇인지 알려줌
- 여러 장치 컨트롤에 연결되어, 각 장치 컨트롤러의 하드웨어 인터럽트의 우선순위를 판단.
- PIC란 ?
- NMI (non-maskable interrupt )란 ? : 가장 우선순위가 높은 하드웨어 인터럽트
- 각 인터럽트의 우선순위를 고려하여 처리하는 방식이다. 만약 마우스와 프린터기에서 인터럽트를 발생시켰을경우, 우선순위가 높은 마우스를 언제나 우선적으로 처리한다.
만약, 프린터기의 인터럽트가 조금 빨리 발생해, 프런터기의 인터럽트 서비스 루틴을 실행 중이더라도, 마우스 인터럽트가 발생할 경우, 프린터기의 인터럽트 서비스 루틴을 잠시 중단하고 마우스 인터럽트 서비스 루틴을 먼저 실행한다.
- PIC (Programmable Intrrupt Controller)를 사용
- 우선순위
프로그램 입출력 ↔️ 인터럽트 입출력
- 공통점
- 입출력 장치 ↔️ 메모리 간 데이터 이동은 CPU가 주도, 이동하는 데이터는 반드시 CPU를 거침
3. DMA (Direct Memory Access) 입출력
- 위의 프로그램 입출력, 인터럽트 입출력은 이동하는 데이터들에 대해 항상 CPU가 주도하고, CPU를 거쳤다.
이렇게 데이터가 CPU에 거치는 과정을 없애기 위해, I/O 장치가 직접 메모리에 접근해 데이터를 주고 받는 기능. - DMA 컨트롤러가 주도 ➡️ CPU의 인터럽트 작업 대리자 .
- DMA 입출력 과정
- CPU가 DMA 컨트롤러에 입출력 장업을 명령
- DMA 컨트롤러는 CPU를 대신 장치 컨트롤러와 상호작용하며 입출력 작업 수행
- 입출력 작업 완료 후, DMA 컨트롤러는 인터럽트를 통해 CPU에게 작업이 끝났음을 알림
이때, 시스템 버스는 공용 자원 ➡️ CPU와 DMA 컨트롤러가 동시에 시스템 버스 사용 불가능. DMA 컨트롤러는 아래와 같이 시스템 버스를 이용 (Cycle Stealing) .
- CPU가 시스템 버스를 이용하지 않을 때, 조금씩 시스템 버스를 이용
- (1번의 과정이 불가능할 경우, )CPU가 잠시 시스템 버스를 이용하지 않도록 허락을 구함.
또한, 공용 자원인 시스템 버스의 사용 빈도를 줄이기 위해, 각 I/O 장치들은 " DMA 컨트롤러 ↔️ (시스템 버스) ↔️ 각 I/O장치의 장치 컨트롤러"가 아닌, "DMA 컨트롤러 ↔️ (입출력 버스) ↔️ I/O 장치의 장치 컨트롤러"로 연결되어 작동된다.
입출력 버스 종류 : PCI 버스, PCIe 버스 (PCI express)
강의 및 참고 출처
https://www.youtube.com/watch?v=kFWP6sFKyp0&list=PLYH7OjNUOWLUz15j4Q9M6INxK5J3-59GC
'CS' 카테고리의 다른 글
[JAVA] - GC(Garbage Collection) 가비지 컬렉션 정리 (0) | 2024.03.10 |
---|---|
[컴퓨터구조] 캐시 메모리 (0) | 2024.03.10 |
[JAVA] 객체 지향 설계의 5원칙 - SOLID 정리 (0) | 2024.03.10 |
운영체제 - 프로세스와 스레드 (0) | 2024.03.10 |
운영체제 정리! -2 (0) | 2024.03.10 |