본문 바로가기
CS

혼자 공부하는 컴퓨터구조 + 운영체제 (1)

by heon28 2024. 3. 31.

개요

<개발자를 위한 컴퓨터공학 1: 혼자 공부하는 컴퓨터구조 + 운영체제>

책과 함께 인프런 강의를 수강하며 공부한 내용을 정리하고자 한다. 책과 강의를 이용하면 더욱 자세한 설명과 이해가 가능하다.

이번 글은 "챕터1~8"까지 컴퓨터구조 에 대해서 공부한 내용을 정리했다.

다음 "챕터9~15까지 컴퓨터구조" 를 정리한 내용은 다음 링크를 참고바란다.

 

키워드 정리

 

내용

Chpater 01. 컴퓨터 구조 시작하기

01-1) 컴퓨터 구조를 알아야 하는 이유

  • 문제해결 : 문법에 맞는 코드 작성 뿐만 아니라 컴퓨터 내부를 뜯어볼 수 있다는 것
  • 성능, 용량, 비용을 고려할 수 있게 됨

01-2) 컴퓨터 구조의 큰 그림

컴퓨터가 이해하는 정보

  • 데이터(Data) : 숫자, 문자, 이미지, 동영상과 같은 정적인 정보
  • 명령어(Instruction) : 데이터를 움직이고 컴퓨터를 작동시키는 정보

컴퓨터의 4가지 핵심 부품 개요

  • 1) CPU(Central Processing Unit; Central/main processor)
    • 메모리에 저장된 명령어를 읽어 들이고, 해석하고, 실행하는 부품
    • (1) 산술논리연산장치(ALU; Arithmetic Logic Unit) : 계산기로 컴퓨터 내부 수행되는 대부분의 계산을 여기서 함
    • (2) 레지스터(Register) : CPU 내부의 작은 저장장치
    • (3) 제어장치(CU; Control Unit) : 제어 신호를 발생시키고, 명령어를 해석하는 장치
      • 제어신호(control signal)
        • 컴퓨터 부품들을 관리하고 작동시키기 위한 전기신호.
        • "메모리 읽기"라는 제어신호, "메모리 쓰기"라는 제어신호가 있음
  • 2) 주기억장치(main memory)
    • 주기억장치 H/W 종류
      • RAM(Random Access Memory) : 보통 메인메모리는 RAM이라고 생각하면 됨. 아래 설명도 이에 해당
      • ROM(Read Only Memory)
    • 현재 실행되는 프로그램의 명령어와 데이터를 저장하는 부품
    • 주소(address) : 메모리에 저장된 값이 어디에 저장되어 있는지 알려주는 개념
  • 3) 보조기억장치(secondary storage)
    • 현재 실행되고 있지 않은 프로그램의 명령어와 데이터를 저장하는 부품
    • 전원이 꺼져도 보관될 프로그램을 저장하기 위함(주기억장치와 다르게 휘발성이 없음)
  • 4) 입출력장치(I/O device; input/output)
    • 컴퓨터 외부에 연결되어 컴퓨터 내부와 정보를 교환할 수 있는 부품
    • 키보드, 마우스, 모니터 등등
    • 사실, 보조기억장치와 입출력장치를 묶어 주변장치(peripheral device)라고 부르기도 함. 하지만, 보조기억장치는 메모리를 보조하는 특별한 입출력장치라는 것!
  • (+) 메인/마더보드(main/mother board)
    • 위의 4가지 부품을 한 곳에 꽂아넣는 곳
    • 버스(bus) : 컴퓨터 부품들간의 정보를 주고받는 일종의 통로 역할을 함
    • 시스템 버스(system bus) : 컴퓨터의 네 가지 핵심 부품을 연결하난 가장 중요한 버스
      • (1) 주소 버스
      • (2) 데이터 버스
      • (3) 제어 버스
      • 예시)
        • 명령어 읽기 신호 : 메모리 읽기 신호(제어 버스) + 읽고자 하는 주소(주소 버스)
        • 명령어 쓰기 신호 : 메모리 쓰기 신호(제어 버스) + 저장할 주소(주소 버스) + 저장할 데이터(데이터 버스)

Chpater 02. 데이터

02-1) 0과 1로 숫자를 표현하는 방법

비트(bit)

  • 0과 1을 표현하는 가장 작은 정보 단위
  • 1 바이트(byte) : 8비트(8bit)
  • 1 킬로바이트(kB) : 1000바이트(1000byte)
  • 1 메가바이트(MB) : 1000킬로바이트(1000kB)
  • 1 기가바이트(GB) : 1000메가바이트(1000MB)
  • 1 테라바이트(TB) : 1000기가바이트(1000GB)
  • 1024 단위로 묶은 건, kiB, MiB, GiB 라는 다른 단위

워드(word)

  • CPU가 한 번에 처리할 수 있는 정보의 크기 단위 : 32비트, 64비트 등등
  • 하프워드, 풀워드, 더블워드가 존재함

2진법(binary)

  • 표현법
    • 1000_(2) : 숫자 아래에 괄호로 작게 (2)를 기재
    • 0b1000 : 숫자 앞에 "0b"를 기재
  • 2의 보수(two's complement)
    • 이진법으로 음수를 표현하는 가장 널리 사용되는 방법 중 하나
    • 구하는 방법
      • 어떤 수를 그보다 큰 2^n에서 뺀 값
      • 좀 더 쉽게 구하는 방법은 모든 0과 1을 뒤집고 1을 더한 값
    • 컴퓨터 내부에서 숫자는 플래그(flag)가 있기 때문에 양수, 음수가 구분 가능함
  • 그 외
    • 10진법(decimal)
    • 16진법(hexadecimal) 표현법 : 15_(16), 0x15(코드상표기방식)

02-2) 0과 1로 문자를 표현하는 방법

문자 집합

  • 문자 집합(character set) : 컴퓨터가 이해할 수 있는 문자의 모음
  • 문자 인코딩(encoding) : 코드화하는 과정으로 문자를 binary로 이루어진 문자코드로 변환하는 과정
    • 코드 포인트(code point) : 문자에 부여된 고유한 값. ex) "A" -> 65_(10)(코드포인트)
  • 문자 디코딩(decoding) : 코드를 해석하는 과정으로 binary 문자코드를 문자로 변환하는 과정

아스키코드(ASCII; American Standard Code for Information Interchange)

  • 알파벳, 아라비아숫자, 일부 특수문자 및 제어문자
  • 7비트로 하나의 문자 표현 -> 128개의 문자 표현가능
  • 8비트 중 1비트는 오류 검출을 위해 사용되는 패리티 비트(parity bit)
  • 단점 : 한글 및 다른 언어 문자, 다양한 특수 문자 표현 불가

한글인코딩

  • 완성형 : 글자 1개마다 코드를 부여한 방식
  • 조합형 : 자음과 모음의 조합으로 초성, 중성, 종성에 자음 모음의 코드를 조합한 방식

EUC-KR

  • 완성형 인코딩
  • 글자 하나에 2byte 크기의 코드 부여. 2300여개의 한글 표현 가능
  • '쀏', '뙠', '휔'과 같은 한글 표현 불가능
  • 언어별 인코딩을 국가마다 하게되면, 다국어를 지원하는 프로그램 개발 시 모든 언어별 인코딩 방식으로 모두 이해하게 해야 함
  • CP949(Code Page 949) :  즉, EUC-KR의 확장 버전이지만 여전히 한글 전체 표현에 넉넉한 양은 아님

유니코드 문자 집합과 utf-8

  • 유니코드(unicode)
    • 통일된 문자집합으로 한글, 영어, 화살표와 같은 특수문자, 심지어 이모티콘까지
    • 인코딩 방식은 문자별 16진수 코드 포인트에 대해 다양한 방식으로 인코딩을 진행하게 됨
  • UTF(Unicode Transformation Format)
    • 가변 길이 인코딩으로 인코딩 결과가 1byte~4byte이고, 각각에 맞게 utf-8, utf-16, utf-21 등등으로 불림
    • 인코딩 결과 길이는 코드포인트 범위에 따라서 다름. ex) 0000 ~ 007F - 1byte, 0080 ~ 07FF - 2byte, ...

Chapter 03. 명령어

03-1) 소스 코드와 명령어

컴퓨터 언어 분류

  • 고급언어(High-level programming language)
    • 개발자가 이해하기 쉽게 만든 언어
    • C++, C, 파이썬, 자바와 같은 대부분의 프로그래밍 언어
  • 저급언어(low-level programming language)
    • 컴퓨터가 이해하기 쉽게 만든 언어
    • 기계어(machine code)
      • 이진수 또는 16진수로 이루어진 명령어
    • 어셈블리어(assembly langugage)
      • 기계어를 읽기 편한 형태로 번역한 언어
      • 예시) 0101 0101 (기계어) -> push rbp (어셈블리어)

컴파일 vs 인터프리터

  • 컴파일 언어(compile language)
    • 컴파일(complie) : 소스코드를 컴파일러(compiler)에 의해 목적 코드로 변경하는 것
      • 소스코드(source code) : 고급 언어로 작성한 코드
      • 목적코드(object code) : 저급 언어로 된 코드
        • 목적코드는 CPU와 컴파일러 종류에 따라서 달라질 수 있음
        • 예시) x86-64 gcc12.2 -> x86-64 CPUDPTJ gcc12.2라는 컴파일러를 이용한 것
        • 변환 예시 사이트 : godbolt.org
  • 인터프리터 언어(interpreter language)
    • 인터프리터(interpreter)에 의해 소스 코드를 한 줄씩 저급언어로 변환하여 실행함
    • 이 때, 인터프리터에 의해 바이트코드(Bytecode)를 생성
      • 바이트코드(Bytecode)
        • 특정 하드웨어가 아닌 가상 컴퓨터에서 돌아가는 실행 프로그램을 위한 이진 표현법
        • 특정 하드웨어의 기계 코드를 만드는 컴파일러의 입력으로 사용되거나 가상 컴퓨터에서 바로 실행함
  • 참고
    • 컴파일 방식과 인터프리터 방식은 하나의 언어에서 한 가지 방식만을 이용하지는 않음!
    • 또한, 경계도 애매함... Java의 경우 사실 컴파일과 인터프린터를 동시에 수행!

C 언어 컴파일 과정

# (1) 전처리기 : 외부라이브러리 코드 확인 가능
gcc -E test.c -o test.i

# (2) 컴파일러 : 어셈블리 언어 확인 가능
gcc -S test.i -o test.s

# (3) 어셈블리 언어가 번역된 기계어 확인 가능(0, 1로 구성)
gcc -o test.o test.s
vi test.o # 참고) xxd test.o; 더 쉽게 볼 수 있음

# (4) 링킹은 아래 설명 참고
  • (1) 전처리기(processor) : test.c -> test.i
    • 외부에 선언된 다양한 소스코드, 라이브러리 포함(#include)
    • 매크로 변환(#define)
    • 컴파일할 영역(#if, #ifdef)
  • (2) 컴파일러(compiler)
    • 전처리기를 통한 소스코드를 저급언어(어셈블리 언어)로 변환
  • (3) 어셈블러(assembler)
    • 어셈블링(assembling)을 통해 어셈블리어를 기계어로 변환
    • 목적코드(object code)를 포함하는 목적파일(object file)이 됨
  • (4) 링커(linker) : test.o -> test.exe
    • 목적 코드가 실행 파일이 되기 위해서는 목적 파일들을 연결하는 링킹(linking) 작업을 거쳐야 함
    • 즉, 목적 파일과 실행 파일은 다름. 물론 둘 다 기계어로 이루어진 파일

03-2) 명령어의 구조

명령어 구조

  • 명령어 = 연산 코드 필드 + 오퍼랜드 필드(=주소랜드 필드)
  • 예시) 어셈블리 코드 "mov eax, 0"
    • 연산코드 : mov
    • 오퍼랜드 : eax, 0
  • 연산코드(operation code)
    • 연산자로서 수행할 연산을 의미
  • 오퍼랜드(operand)
    • 피연산자로서 연산에 사용될 데이터가 저장된 위치(주소필드) 또는 데이터
    • 하나의 명령어 구조에는 오퍼랜드가 0개, 1개, 2개 등등을 가질 수 있는데 이에 따라, 0,1,2,3-주소명령어 라고 부름

연산코드 종류 (종류&생김새는 CPU마다 다름)

데이터 전송
  • MOVE : 데이터를 옮겨라
  • STORE : 메모리에 저장하라
  • LOAD (FETCH) : 메모리에서 CPU로 데이터를 가져와라
  • PUSH : 스택에 데이터를 저장하라
  • POP : 스택의 최상단 데이터를 가져와라
산술/논리 연산
  • ADD / SUBTRACT / MULTIPLY / DIVIDE
  • INCREMENT / DECREMENT : 오퍼랜드에 1을 더하라 / 1을 빼라
  • AND / OR / NOT
  • COMPARE : 2개의 숫자 또는 TRUE, FALSE 값을 비교하라
제어 흐름 변경
  • JUMP : 특정 주소로 실행 순서를 옮겨라. ex) JUMP 120 -> 120번째 주소의 명령어를 실행해라
  • CONDITIONAL JUMP : 조건에 부합할 때 특정 주소로 실행 순서를 옮겨라
  • HALT : 프로그램의 실행을 멈춰라
  • CALL : 되돌아올 주소를 저장한 채 특정 주소로 실행 순서를 옮겨라
  • RETURN : CALL을 호출할 때 저장했던 주소로 돌아가라
입출력 제어
  • READ(INPUT) : 특정 입출력 장치로부터 데이터를 읽어라
  • WRITE(OUTPUT) : 특정 입출력 장치로 데이터를 써라
  • START IO : 입출력 장치를 시작하라
  • TEST IO : 입출력 장치의 상태를 확인하라

 

명령어 주소 지정방식(addressing mode) = 오퍼랜드 필드 명시 방법

  • 명령어 길이가 제한적이므로 보통 오퍼랜드 필드에는 주로 메모리나 레지스터의 주소를 표기함 (오퍼랜드 필드 = 주소필드)
    • 2주소-명령어의 길이가 16비트 : 연산 코드 필드가 4비트 -> 나머지 오퍼랜드필드 길이는 6비트씩(2^6=64...주소도 빠듯)
  • 명령어 오퍼랜드 필드의 주소를 통해 최종적으로 연산에 사용할 유효주소(effective address)를 찾는 다양한 방식
    • 유효주소(effective address) : 연산에 사용할 데이터가 저장된 위치

명령어 주소 지정방식 종류

  • (1) 즉시 주소 지정 방식 (immediate addressing mode)
    • 연산에 사용할 데이터를 직접 명시
    • 연산에 사용할 데이터 크기가 작지만 빠르고 가장 간단함
  • (2) 직접 주소 지정 방식 (direct addressing mode)
    • 유효 주소를 직접적으로 명시
    • 유효 주소를 표현할 수 있는 크기가 연산 코드만큼 줄어듦
  • (3) 간접 주소 지정 방식 (indirect addressing mode)
    • 유효 주소의 주소를 명시
    • 앞의 두 방식보다는 속도가 느림 (메모리를 찾는 건 매우 시간이 오래 걸림)
  • (4) 레지스터 주소 지정 방식 (register addressing mode)
    • 연산에 사용할 데이터가 저장된 레지스터를 명시
    • 메모리 접근 속도보다는 훨씬 빠름
  • (5) 레지스터 간접 주소 지정 방식 (register indirect addressing mode)
    • 유효주소가 저장된 레지스터를 명시

Chapter 04. CPU의 작동 원리

04-1) ALU와 제어장치

산술논리연산장치(ALU; Arithmetic Logic Unit)

  • 받아들이는 정보
    • (1) 피연산자s from 레지스터s
    • (2) 제어신호 from 제어장치 (제어신호를 통해 수행할 연산을 알 수 있음)
  • 내보내는 정보
    • (1) 결괏값 to 레지스터 (숫자,문자,주소 등등)
    • (2) 플래그 to 플래그레지스터 (연산 결과에 대한 부가 정보)
  • 이외에도 다양한 회로가 존재함. 가산기(덧셈), 보수기(뺄셈), 시프터(시프트연산), 오버플로우 검출기 등등

플래그(flag)

  • ALU의 연산 결과에 대한 추가적인 정보로 "플래그 레지스터"에 저장됨
  • 대표적인 종류 : 부호/제로/캐리(올림수,빌림수 발생)/오버플로우/인터럽트/슈퍼바이저(커널,사용자모드) 플래그

제어장치(Control Unit)

  • 받아들이는 정보
    • (1) 클럭(clock)
      • 컴퓨터의 모든 부품을 움직일 수 있게하는 시간 단위로 "똑-딱-똑-딱" 주기를 알려줌
      • 예시) "똑-딱"에 맞게 레지스터 내 데이터 이동, ALU 연산 수행, 메모리에 저장된 명령어 읽기 등을 수행함
      • 박자에 맞춰서 작동하는 건 맞지만, 한 박자마다 작동하는 건 아님! 하나의 명령어가 여러 클럭에 걸쳐서 실행될 수도 있음
    • (2) 해석할 명령어
      • "명령어 레지스터"로부터 명령어를 받아들이고 해석한 뒤, 컴퓨터 부품들이 수행할 내용과 관련된 제어신호를 발생시킴
    • (3) 플래그(flag)
      • "플래그 레지스터"로부터 받아들이는 값
    • (4) 제어신호
      • CPU 뿐만 아니라 입출력장치를 비롯한 주변장치들도 제어신호를 발생시킴
  • 내보내는 정보
    • (1) 제어 신호 to 레지스터
      • 레지스터 간 정보 이동, 값 저장 등의 행동을 지시
    • (2) 제어 신호 to ALU
      • 수행할 연산을 지시
    • (3) 제어 신호 to 메모리
      • 메모리를 읽어라, 써라 등등을 지시
    • (4) 제어 신호 to 입출력장치
      • 입출력장치를 읽어라, 써라, 테스트해라 등등을 지시
    • 이 때, 제어 버스(시스템 버스 중 하나)를 이용하여 제어 신호를 내보냄!

04-2) 레지스터

레지스터(Register)

  • CPU 내부의 작은 임시저장장치로 프로그램 속 명령어 & 데이터는 실행 전후로 레지스터에 저장되고 이는 개발자가 확인 가능함
  • 레지스터의 종류는 다양하고, CPU마다 다름

중요 레지스터 종류

  • (1) 프로그램 카운터(PC; Program Counter)
    • 메모리에서 가져올 명령어의 주소를 저장
    • 명령어 포인터(IP; Instruction Pointer)라고도 부름
    • 명령어를 하나씩 실행할 때마다 프로그램 카운터는 1씩 증가하면서 프로그램을 차례대로 실행!!
    • 단, 순차적인 흐름이 끊기는 경우
      • (A) JUMP, CONDITIONAL JUMP, CALL, RET과 같은 특정 메모리 주소로 실행 흐름을 이동하는 명령어
      • (B) 인터럽트 발생 시, 그 외 기타 등등
  • (2) 명령어 레지스터(IR; Instruction Register)
    • 해석할 명령어를 저장(방금 메모리에서 읽어 들인 명령어) - 제어장치가 해석함
  • (3) 메모리 주소 레지스터(MAR; Memory Address Register)
    • 메모리의 주소를 저장
    • CPU가 읽어들이고자 하는 주소 값을 주소 버스로 보내기 전에 거치게 곳
  • (4) 메모리 버퍼 레지스터(MBR; Memory Buffer Register)
    • 메모리와 주고 받을 데이터와 명령어를 저장
    • 즉, 메모리에 쓰고 싶은 값이나 메모리로부터 전달받은 값이 거치게 되는 곳
    • 데이터 버스로 주고 받을 값이 거치는 곳
    • 메모리 데이터 레지스터(MDR; Memory Data Register)라고도 부름
  • (5) 플래그 레지스터(flag register)
    • 연산 결과 또는 CPU 상태에 대한 부가적인 정보를 저장
  • (6) 범용 레지스터(general purpose register)
    • 다양하고 일반적인 상황에서 자유롭게 사용
    • 주소, 데이터, 명령어 등등 다양하게 저장 가능

주소 지정 방식과 관련된 레지스터 종류

  • (7) 스택 포인터(stack pointer)
    • 스택의 꼭대기 주소를 가리키는 레지스터 (스택이 어디까지 차 있는지에 대해 명시)
    • 스택 주소 지정 방식
      • 스택과 스택 포인터를 이용한 주소 지정 방식
      • 사실, 스택은 메모리 안에 미리 지정된 구역으로 배정되어 있음! 이를 '스택 영역'이라 함!
  • (8) 베이스 레지스터
    • "변위 주소 지정 방식" 중 "베이스 레지스터 주소 지정 방식"의 기준 주소를 저장함
    • 변위 주소 지정 방식
      • 오퍼랜드 필드의 값과 특정 레지스터의 값을 더하여 유효주소를 얻는 방식
      • 명령어 구조 = 연산코드필드 + 레지스터필드 + 오퍼랜드 필드
      • 대표적으로 2가지 방식이 존재하는데
        • (A) 상대 주소 지정 방식 : 오퍼랜드 필드 값 + 프로그램 카운터 값 = 유효주소
          • 예시) 오퍼랜드 필드값이 -3인 경우 -> 현재 프로그램 카운터가 가리키는 명령어로부터 3번째 이전 명령어를 실행하라는 뜻
        • (B) 베이스 레지스터 주소 지정 방식 : 오퍼랜드 필드 값 + 베이스 레지스터 값 = 유효주소
          • 예시) 베이스 레지스터 값이 200, 오퍼랜드 필드값이 3인 경우 -> 200번째 명령어로부터 3번째 이후 명령어를 실행하라는 뜻

04-3) 명령어 사이클과 인터럽트

명령어 사이클(instruction cycle)

  • 기본적으로 "인출-실행-인출-실행-..."이 기본
  • 인출 사이클(fetch cycle) : 메모리에 있는 명령어를 CPU로 가지고 오는 단계
  • 실행 사이클(execution cycle) : CPU로 가져온 명령어를 실행하는 단계
  • 간접 사이클(indirect cycle) : 오퍼랜드 필드에 유효 주소의 주소를 명시한 경우, 메모리 접근이 더 필요한 경우에 실행
  • 인터럽트 사이클(interrupt cycle)

인터럽트(interrupt)

  • CPU의 작업을 방해하거나 중단하는 신호
  • 동기 인터럽트(synchronous interrupts) : CPU가 예상치 못한 상황을 접했을 때 발생. 예외(exception)라고도 불림!
  • 비동기 인터럽트(asynchronous interrupts) : 주로 입출력장치에서 발생. 하드웨어 인터럽트라고도 불리는 듯?

비동기 인터럽트(=하드웨어 인터럽트) 처리 순서

  • (1) 입출력장치는 CPU에 인터럽트 요청 신호를 보냄
  • (2) CPU 실행 사이클이 끝나고, 인출 사이클을 하기 전 항상 인터럽트 여부를 확인
  • (3) 인터럽트 요청을 확인하고, 인터럽트 플래그를 통해 현재 인터럽트를 받아들일 수 있는지 확인함
    • 인터럽트 플래그로 막을 수 있는지 없는지 여부에 따라 "막을 수 있는(maskable) 인터럽트", **"막을 수 없는(non maskable) 인터럽트(NMI)"**로 분류함
  • (4) 인터럽트를 받아들일 시, CPU 내 지금까지의 작업을 스택에 백업
  • (5) CPU는 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴을 실행
    • 인터럽트 서비스 루틴 또한 프로그램이므로 메모리에 저장되어 있음
    • 각 입출력장치의 인터럽트마다 서로 다른 인터럽트 서비스 루틴 시작 주소를 가지고 있음
    • 이 때, 각 인터럽트 서비스 루틴을 식별하기 위한 정보를 인터럽트 벡터라고 부르고 벡터들을 모아놓은 인터럽트 벡터 테이블이라 함
    • 보통은 입출력장치가 인터럽트를 발생시킬 때, "인터럽트 요청 신호 + 인터럽트 벡터(데이터버스)"를 통해 보내게 됨
  • (6) 인터럽트 서비스 루틴 실행이 끝나면 스택에 백업해 둔 CPU 작업 데이터를 복구하여 실행을 재개

Chapter 05. CPU 성능 향상 기법

05-1) 빠른 CPU를 위한 설계 기법

클럭

  • 컴퓨터의 모든 부품들이 클럭 신호에 맞게 일사불란하게 움직이게 하는 시간 단위(막 항상 시간 간격이 일정하지는 않음)
  • 클럭속도(헤르츠(Hz), 1초에 클럭이 반복되는 횟수)가 빠르면 대체로 빠른 컴퓨터일까? 일반적으로는 Yes
  • 하지만, 필요 이상으로 클럭을 높이면 발열이 심각해져 속도가 마냥 빨라지지만은 않음

코어(Core)

  • 전통적인 관점에서 CPU는 명령어를 실행하는 부품으로 원칙적으로는 1개만 존재했었음
  • 하지만, 오늘날 CPU 내 '명령어를 실행하는 부품'은 여러 개가 존재하므로 이 중 '명령어를 실행하는 부품'의 용어를 다시 코어라고 정의함
  • 즉, 하나의 CPU 내 2개 이상의 코어를 가지는 경우 멀티코어라고 부르게 되고, 1개만 있는 경우 싱글코어라고 부르게 됨
  • 코어 수에 비례하게 연산 속도가 증가하나? No!

스레드(Thread)

  • 흔히, 실행 흐름의 단위라고 함. 하지만, 이를 정확히 이해하기 위해 하드웨어적 스레드와 소프트웨어적 스레드로 구분해야 함!
  • 하드웨어 스레드 (= 논리 프로세서)
    • 하나의 코어가 동시에 처리하는 명령어 단위
    • 예시) 2개의 코어를 이용하여 한 번에 4개의 명령어 단위를 처리할 수 있다면, 2코어 4스레드라고 부름! (각 코어 당 2개의 명령어 씩 처리할 듯)
  • 소프트웨어 스레드
    • 하나의 프로그램에서 독립적으로 실행되는 단위
    • 메모리 내 동일 프로그램에서 2개 이상의 영역이 실행되는 경우, 멀티스레드라고 부름!
  • 여기서 중요한 점은 "1코어 1스레드 CPU"도 "여러 소프트웨어 스레드"를 만들 수 있음!!
  • 멀티스레드 프로세서를 실제로 설계하는 일은 매우 복잡하지만, 가장 큰 핵심은 레지스터
    • 하나의 코어 내 '레지스터 세트'가 여러개 있으면 여러 명령어를 동시에 처리할 수 있음!!
    • 레지스터 세트 : 하나의 명령어를 실행하기 위해 꼭 필요한 레지스터 묶음

05-2) 명령어 병렬 처리 기법

명령어 파이프라인 (1개)

  • 여러 명령어의 단계를 서로 겹쳐서 병렬로 실행하는 방법
  • 명령어 단계 : 명령어 인출, 명령어 해석, 명령어 실행, 결과 저장 등으로 구분. 책마다 조금씩 다름...
  • 같은 단계가 겹치지만 않으면 CPU는 각 단계를 동시에 실행할 수 있음!!
  • 예시) "명령어1-인출", "명령어2-해석", "명령어3-실행" 을 동시에 수행 가능!!

파이프라인 위험

  • 데이터 위험
    • 명령어 간의 의존성에 의해 발생
    • 예시) 명령어1 : R1 <- R2 + R3. 명령어2 : R4 <- R1 + R5
  • 제어 위험
    • 프로그램 카운터의 갑작스러운 변화에 의해 발생
    • 예시) JUMP, CALL, INTERRUPT 등등
    • 보통은, 10번지 명령어, 11번지 명령어, 12번지 명령어를 순차적으로 실행함. 그런데 10번지에서 60번지로 뛰어넘어갈 시, 11번지, 12번지 명령어 동시 진행은 헛수고가 됨
    • 분기예측(branch prediction) : 프로그램 카운터가 어느 번지로 점프할 건지 미리 예측하는 기술도 있긴 함
  • 구조적 위험
    • 서로 다른 명령어가 같은 CPU 부품(ALU, 레지스터)를 쓰려고 할 때 발생

슈퍼 스칼라

  • CPU 내부에 여러 개의 명령어 파이프라인을 포함한 구조
  • 8코어 16스레드인 경우, 16개의 명령어를 한 번에 진행할 수 있는 구조로, 각 16개 스레드에 대해 명령어 파이프라인을 수행함
  • 이론적으로 파이프라인의 개수에 비례해 처리속도가 증가해야하나, 파이프라인 위험도의 증가로 비례하진 않음

비순차적 명령어 처리

  • 명령어 간의 합법적인 새치기 방법
  • 만약, 의존성이 없는 명령어의 순서를 바꿔도 결과에는 영향이 없고 명령어 파이프라인도 더 효율적으로 사용됨

05-2) 명령어 집합 구조, CISC와 RISC

: 명령어 파이프라인에 유리한 명령어 집합 구조가 필요함!!

명령어 집합(instruction set)

  • CPU가 이해할 수 있는 명령어들의 모음
  • 어떻게 보면 CPU의 언어이자 하드웨어가 소프트웨어를 어떻게 이해할지에 대한 약속인 셈
  • 명령어 집합 구조(ISA; Instruction Set Architecture)라고도 부름

CISC(Complex Instructino Set Computer)

  • 복잡한 명령어 집합을 활용하는 컴퓨터로 명령어의 형태와 크기가 다양한 가변 길이 명령어를 활용
  • 예시) x86, x86-64
  • 장점
    • 다양하고 강력한 명령어가 존재하므로 상대적으로 적은 수의 명령어로도 프로그램 실행 가능
    • 적은 수의 명령어만 있으면 되기 때문에 메모리를 최대한 아끼며 개발해야했던 시절에는 인기가 높았음!
    • 다양한 주소 지정방식도 지원함
  • 단점 : 명령어 파이프라이닝이 불리다하다는 치명적인 단점
    • 명령어가 복잡하고 다양한 기능을 제공하므로 명령어의 크기와 실행되기까지의 시간이 일정하지 않음
    • 복잡한 명령어로 인해 명령어 하나를 실행하는데 여러 클러 주기가 필요함
    • 사실, 대다수의 복잡한 명령어는 사용빈도가 낮음

RISC(Reduced Instruction Set Computer)

  • 명령어의 종류가 적고, 짧고 규격화된 명령어를 활용
  • 장점 : 명령어 파이프라이닝에 유리함
    • 규격화된 명령어를 통해 1클럭 내외로 명령어 수행
    • 일반적으로 메모리 메모리 접근 방식을 최소화(load, stroe)하고 레지스터를 최대한 활용함 -> 범용 레지스터를 많이 활용
    • 적은 주소 지정방식
  • 단점
    • 명령어 종류가 적으므로, 더 많은 명령어로 프로그램을 동작시킴

현대 CPU는 CISC 기반의 제조사에서도 명령어보다도 더 작은 단위 "마이크로단위"로 더 쪼갠 후 내부적으로 RISK처럼 사용하긴 함...

Chapter 06. 메모리와 캐시메모리

06-1) RAM의 특징과 종류

RAM = 휘발성 저장 장치 보조기억장치 = 비휘발성 저장 장치

DRAM(Dynamic RAM)

  • 저장된 데이터가 동적으로 사라지는 RAM
  • 데이터 소멸을 막기 위해 주기적으로 활성해줘야 함
  • 상대적으로 소비전력이 낮고 저렴하고 집적도가 높아 대용량으로 설계하기 용이함

SRAM(Static RAM)

  • 저장된 데이터가 정적인(사라지지 않는) RAM
  • DRAM보다는 일반적으로 더 빠름
  • 소비전력이 높고 가격이 높고 집적도가 낮아 대용량으로 설계할 필요가 없는 경우 용이함

SDRAM (Synchronou DRAM)

  • 동기화된 DRAM. 즉, 클럭신호와 동기화된 DRAM
  • SDR SDRAM과 동일. Single Data Rate SDRAM

DDR SDRAM (Double Data Rate SDRAM)

  • 대역폭을 넓혀 속도를 빠르게 만든 SDRAM. 대역폭이 SDRAM의 2배.
  • 대역폭 = 데이터를 주고받는 길의 너비
  • 대역폭 더 늘린 버전
    • DDR2 SDRAM : DDR SDRAM보다도 대역폭이 2배
    • DDR3 SDRAM : DDR2 X 2
    • DDR4 SDRAM : DDR3 X 2
  • 가장 대중적임 : 보통 DDR4를 씀

06-2) 메모리의 주소 공간

메모리 주소 공간의 구분

  • CPU와 실행 중인 프로그램은 현재 메모리 몇 번지에 무엇이 저장되었는지 다 알고 있나? No
    • 메모리에 저장된 값은 변하기 때문. 프로그램이 새롭게 실행되거나 끝나거나 또는 같은 프로그램이라도 실행할 때마다 주소는 달라짐
  • 이를 극복하고자 주소를 구분함
    • 논리주소 : CPU와 프로그램 기준에서 바라본 주소. 실행 중인 프로그램의 0번지부터 시작하는 주소
    • 물리주소 : 메모리 기준. 실제로 저장된 하드웨어 상의 주소.

MMU(Memory Managemnet Unit; 메모리 관리장치)

  • 물리주소와 논리주소 사이의 변환을 이루어주는 장치
  • CPU가 사용하는 주소는 모두 논리주소. 이 때, 주소버스를 통해서 메모리에 쏘거나, 메모리로부터 주소를 받을 때는 항상 MMU를 거치게 됨!
  • 논리주소와 베이스 레지스터 값을 더하여 물리주소로 변환함!
  • 베이스레지스터 : 프로그램의 가장 작은 물리주소(프로그램의 첫 물리 주소)를 저장하는 셈임!
  • 논리주소 : 프로그램의 시작점으로부터 떨어진 거리인 셈!

메모리 보호 기법

  • 한계 레지스터(limit register) : 논리 주소의 최대 크기를 저장하여 타 프로그램의 영역을 침범할 수 있는 명령어의 실행을 막음
  • 베이스 레지스터값 <= 프로그램의 물리주소 범위 < 베이스 레지스터값 + 한계 레지스터값
  • 따라서, CPU가 메모리에 접근하기 위한 논리주소가 한계 레지스터보다 작은지를 항상 검사하게 됨. 넘어가면, 인터럽트(트랩) 발생!

06-3) 캐시 메모리

CPU가 메모리에 접근하는 시간은 CPU 연산 속도보다 훨씬 느리다!!

저장 장치 계층 구조(memory hierarchy)

  • CPU와 가까울수록 빠르고, 멀수록 느리다. 그리고 속도가 빠른 저장 장치는 저장 용량이 작고 가격이 비싸다
  • 레지스터 vs 메모리(RAM) vs 보조기억장치 : 속도 vs 용량 vs 가격

캐시 메모리

  • CPU와 메모리 사이에 위치한 레지스터보다는 용량이 크고 메모리보다는 빠른 SRAM 기반의 저장 장치
  • CPU가 사용할 일부 데이터를 미리 캐시 메모리로 가지고 와서 쓰자!!
  • 저장 장치 계층 구조(memory hierarchy) : 레지스터 - 캐시메모리 - 메모리 - 보조기억장치
  • 계층적 캐시 메모리 : L1-L2-L3 캐시
    • L1, L2는 코어 내부에, L3는 코어 외부에 위치
  • 분리형 캐시(split cache) : L1 캐시의 접근 속도를 빠르게 만들기 위해 분리한 것
    • L1I : 명령어만을 저장하는 L1 캐시
    • L1D : 데이터만을 저장하는 L1 캐시

참조 지역성의 원리

  • 캐시 메모리는 메모리보다 용량이 작으므로 CPU가 자주 사용할 법한 내용을 예측하여 저장해야 하므로 위의 원리가 중요함
  • 캐시 적중률 = 캐시히트 횟수 / (캐시히트 횟수 + 캐시미스 횟수)
    • 캐시히트(예측이 맞은 경우, CPU가 캐시 메모리에 저장된 값을 활용한 경우)
    • 캐시미스(예측이 틀린 경우, CPU가 캐시 메모리에 저장된 값을 활용하지 않는 경우)
  • CPU가 메모리에 접근할 때의 주된 경향성
    • 최근에 접근했던 메모리 공간에 다시 접근하려는 경향
    • 접근한 메모리 공간 근처를 접근하려는 경향(공간 지역성)

Chapter 07. 보조기억장치

07-1) 다양한 보조기억장치

하드디스크(HDD; Hard Disk Drive)

  • 자기적인 방식으로 데이터 저장하는 보조기억장치. 자기디스크(magnetic disk)의 일종으로 봄
  • 구성요소
    • 플래터(platter) : 실질적인 데이터 저장이 일어나는 곳을 동그란 원판들이 쌓여 있음. 수많은 N극과 S극을 저장하며 0과 1의 역할을 수행함
    • 스핀들(spindle) : 플래터를 회전시키는 구성 요소
      • RPM(Revolution Per Minute) : 플래터를 돌리는 속도로 분당 회전수를 의미
    • 헤드(head) : 플래터에서 데이터를 읽고 쓰는 구성 요소로 플래터의 겹마다 존재함
    • 디스크 암(disk arm) : 헤드를 움직여주는 요소로 헤드마다 존재함. 겹겹이 있는 헤드와 디스크암은 동일하게 움직인다는 특징이 있음
  • 하드디스크 저장단위
    • 트랙(track) : 플래터에서 동심원을 이루는 원 둘레 하나
    • 섹터(sector) : 트랙을 다시 피자조각마냥 나눈 것 (섹터크기 : 512~4096byte)
      • 보통은 트랙(track)과 섹터(sector) 단위로 데이터 저장
    • 블록(block) : 하나 이상의 섹터를 묶은 것
    • 실린더(cylinder) : 여러 겹의 플래터 상에서 같은 트랙이 위치한 곳을 모아 연결한 논리적 단위(약간 원기둥 느낌?)
      • 연속된 정보는 한 실린더에 기록. 한 실린더 내 데이터가 있다면 헤드를 움직이지 않아도 읽어낼 수 있으므로!
  • 데이터 접근 시간
    • 탐색시간 : 접근하려는 데이터가 저장된 트랙(track)까지 헤드를 이동하는 시간(어떤 동심원으로 가야할지 정하는 것)
    • 회전지연 : 헤드가 있는 곳으로 플래터를 회전시키는 시간(트랙 내 섹터로 이동하는 것)
    • 전송시간 : 하드디스크와 컴퓨터 간에 데이터는 전송하는 시간
  • 참고
    • 단일 헤드 디스크(single-head disk)
      • 헤드가 1개인 하드디스크
      • 이동 헤드 디스크(movable-head disk)라고도 부름
    • 다중 헤드 디스크(multiple-head disk)
      • 헤드가 트랙별로 달려있는 하드디스크. 탐색시간이 0이 됨! (모든 원마다 존재하므로!)
      • 고정 헤드 디스크(fixed-head disk)

플래시 메모리(flash memory)

  • 전기적으로 데이터를 읽고 쓰는 반도체 기반 저장장치이지만, 범용성이 넓어 보조기억장치에만 속하는 것은 아님(ROM 등등)
  • 2가지 종류 중 NAND 플래시 메모리 위주로 설명할 예쩡
    • NAND 플래시 메모리 : NAND 게이트(NAND 연산을 수행하는 회로)를 기반으로 한 메모리. 보통은 대용량 저장장치로 많이 사용됨
    • NOR 플래시 메모리 : NOR 게이트(NOR 연산을 수행하는 회로)를 기반으로 한 메모리
  • 플래시메모리 저장단위
    • 셀(cell) : 플래시메모리에서 데이터를 저장하는 가장 작은 단위
      • 플래시메모리 종류에 따라 하나의 셀에 서로 다른 비트를 저장할 수 있고, 1~4비트 각각 SLC/MLC/TLC/QLC 라고 불림
      • SLC : 1비트 -> 2개의 정보표현. 비트의 빠른 입출력, 긴 수명, 용량 대비 고가격
      • MLC : 2비트 -> 4개의 정보표현. 입출력이 조금 느려짐, 수명이 조금은 짧아짐, SLC 보다 비교적 저렴함
      • TLC : 3비트 -> 8개의 정보표현.
      • QLC : 4비트 -> 16개의 정보표현
    • 페이지(page) : 셀이 모인 것. 읽기/쓰기 최소 단위
      • 페이지는 상태를 가짐
        • Free 상태 : 새로운 데이터 저장 가능
        • Valid 상태 : 유효한 데이터가 이미 저장 중
        • Invalid 상태 : 쓰레기값이라 부르는 유효하지 않은 데이터를 저장 중
      • 플래시메모리는 일반적으로 하드디스크와 달리 덮어쓰기가 불가능
    • 블록(block) : 페이지가 모인 것. 삭제 단위. 즉, 읽기/쓰기보다 더 큰 단위로 삭제가 된다는 점!
    • 플레인(plane) : 블록이 모인 것
    • 다이(die) : 플레인이 모인 것
  • 가비지 컬렉션(garbage collection)
    • SSD를 비롯한 최근 플래시 메모리가 블록 내 Valid한 페이지만 다른 블록에 복사 후 기존 블록을 제거하는 것
    • 그러면 기존 블록 내 Invalid한 페이지는 삭제할 수 있음

07-2) RAID의 정의와 종류

스팬 볼륨 (JBOD)

  • 하나의 디스크에 용량이 다 차면 다음 하드디스크에 저장을 하는 방식으로 단순 볼륨을 늘리는 형태
  • 장점
    • 다른 디스크에서 오류가 나도 다른 디스크에 저장된 데이터는 온전히 사용 가능(단, 디스크별로 데이터가 걸치면 안 됨)
    • 디스크별 용량이 달라도 됨
  • 단점
    • 단일 디스크와 속도적인 차이는 없음. 효율적이지 못 함

RAID (Redundant Array of Independt Disks)

  • 여러 물리적 보조기억장치를 마치 하나의 논리적 보조기억장치처럼 사용하는 기술로 안정성과 높은 성능을 위해 사용됨
  • RAID의 레벨이 존재함. RAID 0, RAID 1, RAID 2, ... 등등. 현재 RAID 2,3 은 사용 안 함
  • Nested RAID도 존재하는데 이는 RAID 1과 0을 혼합해 RAID 10, 5와 0을 혼합해 RAID 50 이런 방식임

RAID 0

  • 각 하드디스크의 같은 층(줄무늬)에 연속된 정보를 저장해서 저장된 자료를 병렬적으로 처리하는 방식
    • 스트라입(stripe) : 줄무늬처럼 분산되어 저장된 데이터
    • 스트라이핑(striping) : 분산하여 저장하는 것
  • 장점 : 입출력 속도의 향상. 4개로 나누어서 저장하면 이론 상 하드디스크 1개보다 4배가량 빠름
  • 단점 : 저장된 정보가 안전하지 않음

RAID 1

  • 데이터를 쓸 때, 원본과 복사본 두 군데에 쓰는 방식 (느린 쓰기 속도)
    • 미러링(mirroring) : 복사본을 만드는 방식
  • 장점 : 백업과 복구가 쉬워서 RAID 0 에 비해 안정성이 높음
  • 단점 : 하드 디스크 개수가 한정 되었을 때, 복사본으로 사용할 하드디스크가 필요하므로 사용 가능한 용량이 적어짐

RAID 4

  • RAID 1과 같은 완전한 복사본 대신 패리티 비트를 저장할 장치를 따로 두는 방식
    • 패리티 비트(parity bit)
      • 어떤 하드디스크를 이용해 다른 하드디스크의 오류를 검출하고, 오류가 있다면 복구하는 비트
      • 원래 패리티비트는 오류 검출 용도만 가능. 하지만, RAID에서는 오류 복구도 가능(어떤 계산식에 의해)
  • 장점 : RAID 1 보다 더 안전하고 적은 용량으로 백업 및 복구를 할 수 있음
  • 단점 : 모든 하드디스크들의 쓰기와 함께 패리티비트가 있는 하드디스크의 쓰기가 동시에 일어나므로 병목현상이 발생함

RAID 5

  • RAID 4에서의 패리티 비트를 분산하여 저장하는 방식
  • 하나의 디스크가 다운되어도 그에 맞는 패리티 비트가 다른 하드디스크에 있으므로 괜춘
  • 하드디스크에 쓰기를 진행하고 패리티비트에 쓰기를 진행해도 하나의 디스크에만 저장하는 것은 아니므로 병목을 피할 수 있음

RAID 6

  • RAID 5에서 하드디스크별로 1개의 패리티만 가진다면 RAID 6은 서로 다른 2개의 패리티를 가지는 것
  • RAID 4, 5보다는 안전하지만, 쓰기 속도는 RAID 5보다 느림. 속도를 희생하고 데이터를 안전하게 보관!

Chapter 08. 입출력장치

08-1) 장치 컨트롤러와 장치 드라이버

'CS' 카테고리의 다른 글

혼자 공부하는 컴퓨터구조 + 운영체제 (2)  (2) 2024.04.14
CS지식 개론 - (1) 개발자필수지식  (0) 2024.03.10