컴퓨터 시스템으로의 여행
- 컴퓨터 시스템 = 하드웨어 + 시스템 소프트웨어
- 작동하며 응용프로그램을 실행함.
- 모든 컴퓨터 시스템은 유사한 기능을 수행하는 유사한 하드웨어와 소프트웨어 컴포넌트를 가지고 있다.
1.1 정보는 비트와 컨텍스트로 이루어진다.
- 비트: 데이터
- 컨텍스트: 해석방법
- ⇒ 동일한 비트(데이터)가 컨텍스트에 따라 다르게 해석될 수 있음
✅ 컨텍스트는 어디에서 주어지는 것인가?
좋은 질문이야! 핵심을 짚었네.
결론부터 말하자면:
컨텍스트는 ‘항상 파일 안에 직접 쓰여 있는 건 아니고’, 보통은 ‘외부의 규칙’이나 ‘해석하는 프로그램/환경’이 제공해.
✅ 1. 컨텍스트가 파일 안에 명시적으로 있는 경우
일부 형식 있는 데이터는 스스로를 설명하기 위해 컨텍스트 정보를 내부에 포함해.
이럴 땐 컨텍스트가 직접적으로 쓰여 있는 것이 맞아.
예시:
| 데이터 | 내부 컨텍스트 | 설명 |
|---|---|---|
PDF 파일 | 시작 부분에 %PDF-1.7 | → “나는 PDF 파일이야” |
JPEG 이미지 | FF D8 FF E0 (magic number) | → “나는 JPEG야” |
Python 코드 | 0b1010 | → “이건 2진수 정수야” |
HTML | <html>, <head>, <body> | → “나는 웹 문서야” |
이런 경우는 컨텍스트가 비트/바이트 안에 포함된 경우라고 볼 수 있어.
✅ 2. 컨텍스트가 외부에서 주어지는 경우
하지만 대부분의 경우, 비트 그 자체만 봐서는 해석할 수 없고,
**외부 환경, 프로세스, 해석자(program)**가 그 의미를 부여해줘.
예시:
.txt파일의01000001→ 메모장에서 보면"A"지만, hex editor에선0x410b1010→ 파이썬 코드에서는 2진수 10이지만, 그냥 텍스트 파일로 보면 단순한 문자열"0b1010"- 메모리 안에 있는
8바이트→ 이걸 double로 볼지, int로 볼지는 CPU나 프로그래머가 결정
즉, 이 경우 컨텍스트는 파일 외부에 있어:
- 파일 확장자
- 프로그래밍 언어의 문법
- 운영체제의 실행 규칙
- 사용하는 소프트웨어
🔸 요약
| 컨텍스트는… | 예시 | 파일 안에 있는가? |
|---|---|---|
| 내부에 포함된 경우 | %PDF, <html>, 0b1010 | ✅ 예 |
| 외부 규칙에 따라 해석되는 경우 | 파일 확장자 .exe, 파이썬의 0b를 해석하는 인터프리터 | ❌ 아니오 |
🧠 정리하자면
🔹 컨텍스트는 “해석 기준”이다.
🔹 어떤 데이터는 그 기준을 스스로 안에 담기도 하고,
🔹 어떤 데이터는 *해석하는 주체(사람, 프로그램, OS)*가 기준을 제공하기도 해.
원하는 주제로 더 깊이 들어갈 수 있어! 예를 들어 “컴파일러가 컨텍스트를 어떻게 이해하는가”, “바이너리 파일 해석”, “파이썬 인터프리터의 역할” 같은 것도 연결해서 설명할 수 있어.
1.2 프로그램은 다른 프로그램에 의해 다른 형태로 번역된다.
- 컴파일 시스템
- 소스코드(원시코드)를 목적코드로 바꾸는 역할
- 전처리기, 컴파일러, 어셈블러, 링커의 4단계를 실행하는 프로그램드을 합쳐서 컴파일 시스템이라고 함.
- e.g., GCC 컴파일러 드라이버: 소스파일 hello.c를 읽어서 실행파일인 hello로 번역.
각 단계

- 시작 파일: 소스코드(
.c)
전처리 단계
- 사용 프로그램: 전처리기(cpp)
- 역할:
#문자로 시작하는 디렉티브1에 따라 파일을 수정- e.g.,
#includes<studio.h>: 시스템 헤더파일인 studio.h를 프로그램 문장에 직접 삽입하라는 뜻
- e.g.,
- 결과파일: 수정된 소스코드 파일(
.i)
컴파일 단계
- 사용 프로그램: 컴파일러(cc1)
- 역할: 어셈블리어로 파일을 번역
- 어셈블리어는 기계어와 1:1 대응됨
- 상위수준 언어 종류에 상관 없이 동일한 어셈블리어로 출력파일을 생성
- 결과파일: 어셈블리어 프로그램 파일(
.s)
어셈블리 단계
- 사용 프로그램: 어셈블러(as)
- 역할: 어셈블리어 → 기계어 인스트럭션 ⇒ 결과 파일로…
- 결과파일: 재배치가능 목적프로그램(
.o)
✅ 1. ‘재배치 가능 목적 프로그램’에서 ‘재배치’란?
**“재배치 가능”하다는 말은, 이 목적파일(hello.o) 안의 코드나 데이터가 메모리에서 최종적으로 어디에 위치할지 아직 정해지지 않았고, 나중에 자유롭게 위치를 조정할 수 있게 설계되어 있다는 뜻이야.
🔹 다시 말해:
- **“파일 자체가 이리저리 옮겨진다”**는 의미도 아니고,
- **“인스트럭션들이 뒤죽박죽 위치 바뀐다”**는 뜻도 아니야.
- 대신, 이 의미는 메모리에 올려질 때 “어디에 위치할 수 있는지 유연하다”는 뜻이야.
🔹 예시:
int main() {
return 0;
}이 코드가 컴파일되어 hello.o라는 목적파일이 만들어졌다고 해.
- 여기에는
main함수의 기계어 인스트럭션이 들어 있지만,
“이 코드가 메모리 주소 0x400000부터 실행된다”는 정보는 아직 없음! - 나중에 링커가 여러 목적파일을 결합할 때, 이
main함수가 0x400000에 올릴지, 0x500000에 올릴지는 그때 결정함. - 그래서
hello.o안의 기계어 코드에는 이런 주소가 “심볼”로 남아 있음. (예:main이 아직 어딘지 모르므로main→ 심볼 테이블)
📌 즉, **“재배치 가능”하다는 것은 이 목적파일 안의 주소들이 아직 “결정되지 않았고, 나중에 링커가 마음대로 재배치할 수 있게 만들어진 상태”**라는 뜻이야.
링크 단계
- 사용 프로그램: 링커(ld)
- 역할: 통합작업
- 이미 컴파일된 별도의 목적파일에 들어있는 심볼(함수, 변수 등)을 사용해야할 경우가 많음
- e.g., 외부 함수 사용
- 이러한 심볼들을 연결하여 하나의 실행파일을 생성
- 이미 컴파일된 별도의 목적파일에 들어있는 심볼(함수, 변수 등)을 사용해야할 경우가 많음
- 결과파일: 실행 가능 목적파일(실행파일)
메모리 적재 후 실행
1.3 컴파일 시스템 이해가 중요한 이유
- 프로그램 성능 최적화
- switch문은 if-else문을 연속해서 사용하는 것보다 언제나 더 효율적일까?
- 함수 호출시 발생하는 오버헤드는 얼마나 되는가?
- while 루프는 for 루프보다 더 효율적일까?
- 포인터 참조가 배열 인덱스보다 더 효율적인가?
- 합계를 지역변수에 저장하면 팜조형태로 넘겨받은 인자를 사용하는 것보다 왜 루프가 더 빨리 실행되는가?
- 수식 연산시 괄호를 단수히 재배치하기만 해도 함수가 더 빨리 실행되는 이유는 무엇인가?
- 링크에서 이해하기
- 링커아 어떤 참조를 풀어낼 수 없다고 할 때는 무엇을 의마하는가
- 정적변수와 전역변수의 차이는 무엇?
- 각기 다른 파일에 동일한 이름의 두 개의 전역변수를 정의한다면 무슨일이?
- 정적 라이블리와 동적 라이브러리의 차이는?
- 컴파일 명령을 쉘에서 입력할 때 명령어 라인의 라이브러리들의 순서는 무슨 의미가 있는가?
- 보안 약점 피하기
- e.g., 버퍼 오버플로우 취약성.
- 안전한 프로그래밍의 첫번째 → 스택에 데이터와 제어정보가 저장되는 방식의 영향 이해.
✅ 기억장치
- 속도 빠른 순
[CPU]
└─ 레지스터
└─ 캐시 (L1 → L2 → L3)
[메모리 계층]
└─ RAM (주기억장치)
└─ 버퍼 (I/O 대기용)
└─ 디스크 (SSD/HDD 등)
[외부저장소]
└─ USB, 외장하드, 클라우드 저장소| 용어 | 정의 | 비휘발성 | 속도 | 위치/역할 |
|---|---|---|---|---|
| 저장소 | 모든 비휘발성 저장 매체의 총칭 | O | 느림 | 넓은 개념 |
| 디스크 | 보통 HDD, SSD를 말함. 데이터를 영구 저장하는 장치 | O | 느림 | 보조기억장치 |
| ROM | 읽기전용 메모리. 펌웨어나 시스템 부트로더 등이 저장 | O | 느림 | 메인보드 |
| 버퍼 | 데이터 전송을 조율하기 위한 임시 공간. (느린 장치간 데이터 전송 속도 맞추기 위함) | X(보통) | 중간 | 메모리 or 장치내부 |
| 메모리 | 보통 RAM을 뜻함. 실행중인 데이터/코드를 저장 | X | 빠름 | 주기억장치 |
| 캐시 | CPU 안에 있는 초고속 임시 저장소. 최근/자주 쓰는 데이터를 저장 | X | 매우 빠름 | CPU 내부 |
| 레지스터 | CPU 내부의 초소형 저장공간. 연산에 바로 사용 | X | 최고 속도 | CPU 내부 |
1.4 프로세서는 메모리에 저장된 인스트럭션을 읽고 해석한다.
✅ 쉘과 CLI
- CLI(Command-Line Interface)
- 사용자가 명령어를 입력해 컴퓨터와 상호작용하는 방식
- UI 방식 중 하나로 GUI(마우스, 버튼 등)와 반대
- shell
- 사용자가 CLI를 쓸 수 있도록 운영체제와 사용자 사이를 중계하는 프로그램
- 통역가와 같은 역할을함
- 입력받는 명령어는 내장 쉘명령어 또는 실행파일의 이름임.
- 운영체제
- 명령을 실제 수행하는 주체
하드웨어 구성 요소
Bus
- 시스템 내를 과농하는 전기적 배선군
- 컴포넌트들 간에 바이트 정보를 전송
- 전송하는 정보는 word라는 고정 크기를 가짐 → 대개 4 bytes (32 bits) 나 8 bytes (64 bits)
입출력 장치
- 시스템과 외부세계와의 연결을 담당.
- e.g., 키보드, 마우스, 출력용 디스플레이, 외부 디스크 드라이브
- 각 입출력 장치는 입출력 버스 + (컨트롤러 or 어댑터)를 통해 연결됨2
- 컨트롤러: 디바이스 자체가 칩셋이거나 시스템의 인쇄기판에 장착
- 어댑터: 마더보드의 슬롯에 장착되는 카드
메인 메모리
- 프로세서가 프로그램을 실행하는 동안 데이터와 프로그램을 모두 저장하는 임시 저장장치
- 물리적: DRAM칩들로 구성
- 논리적: 연속적인 바이트들의 배열 → 각 byte들은 고유의 주소를 가짐.
✅RAM
- RAM: 어떤 메모리 주소에 접근(random access)하더라도 동일한 시간의 읽고 쓰기가 보장되어서 random access memory라고 부름
- cf) 하드디스크 vs RAM
- 데이터 주소에 따라 접근 시간이 다름 → 헤드라는 장치를 이용해 플래터라는 원판에 데이터를 읽고 쓰는데, 플래터를 돌려 헤드를 해당주소로 옮겨야함. → 헤드 위치에 따라 접근 시간 달라짐.
- RAM은 전기를 저장하는 cell들의 배열(반도체 회로)로 구성→ cell의 전압정보를 읽어오는데 동일한 시간 소요
- cf) 하드디스크 vs RAM
- 비용: SRAM > DRAM
- 속도: SRAM > DRAM
- ⇒ 메인메모리: DRAM
프로세서
- = 주처리장치(CPU)
- 메인 메모리에 저장된 인스트럭션들을 해독 및 실행하는 엔진
- 프로그램 카운터(PC)
- 메인 메모리의 기계어 인스트럭션의 주솟값을 가짐
- Word크기의 저장장치임. → register내에 존재하기도 함.
- 프로세서는 프로그램 카운터가 가리키는 인스트럭션을 실행하고 PC값은 다음 인스트럭션의 위치로 값을 업데이트하는 행위를 반복함.
- 인스트럭션 실행:
- 메모리로부터 인스트럭션 읽어오기(Fetch)
- 인스트럭션 해석하기(Decode)
- 인스트럭션 실행하기(Execute)
- 인스트럭션 예시:
- 적재(Load): 메인 메모리 → 레지스터
- 저장(Store): 레지스터 → 메인 메모리
- 작업(Operate): 두 레지스터 값 가지고 ALU에서 연산을 수행하고 결과 값을 저장(덮어쓰기)
- 점프(Jump): 인스트럭션 자신으로부터 한 개의 워드를 추출 하고 이것을 PC에 덮어쓰기함.
- 인스트럭션 실행:
프로그램 실행 개괄 → hello 프로그램 실행

1.5 캐시가 중요하다
- 원인1. 데이터 복사 및 이동에 많은 시간이 소요 → 실제 작업 속도를 저해
- 빠른 복사와 빠른 이동이 중요해짐
- 원인2. 프로세서의 속도 향상이 메모리의 속도 향상보다 더 쉽고 더 쌈.
- 프로세서와 메모리 간의 속도 격차가 발생
- “캐시”: 작으면서 빠른 캐시 메모리를 고안
- 단기간에 프로세서에서 사용할 가능성이 높은 데이터들을 임시 저장해둠.
- SRAM을 사용
1.6 저장장치들은 계층구조를 이룬다

- 주요 아이디어는 한 레벨의 저장장치가 다음 하위레벨 저장장치의 캐시 역할을 한다는 것
1.7 운영체제는 하드웨어를 관리한다.

- 운영체제: 하드웨어와 소프트 웨어 사이에 위치한 소프트웨어 계층
- 응용프로그램이 하드웨어를 사용하려면 무조건 운영체제를 거쳐야함
- Why?
- 제멋대로 동작하는 응용프로그램들이 하드웨어를 잘못사용하는 것을 방지
- 메모리 주소를 잘못 참조하면 → 다른 프로그램 메모리를 침범할 수 있어3
- 프린터를 동시에 여러 앱이 사용하면 → 출력 충돌이 날 수 있어
- 저장장치를 잘못 쓰면 → 파일 손상 발생
- CPU를 혼자 다 쓰는 프로그램이 있으면 → 다른 프로그램이 멈춤
- 단순하고 균일한 매커니즘을 사용하여 복잡하고 매우 다른 저수준 하드웨어 장치들을 조작할 수 있도록 하기위해
- 종류, 제조사마다 모두 동작 방식이 다 달라
- 이걸 응용프로그램이 직접 처리해야 한다면? → 너무 복잡하고 오류 많음
- e.g., 파일을 읽고싶으면, 해당파일을 그냥 지정해주면 됨. 그 파일이 SDD에 있든, USB에 있든 상관 없음
- 제멋대로 동작하는 응용프로그램들이 하드웨어를 잘못사용하는 것을 방지
- Why?
추상화
- 위의 목적을 추상화를 통해 달성 → 맘대로 접근하지 못하게 숨겨놓음
- 추상화 형태

- 파일: 입출력 장치의 추상화
- 가상 메모리: 메인메모리와 입출력 장치의 추상화
- 프로세스: 프로세서, 메인메모리, 입출력장치 전체의 추상화
프로세스
-
환상 → 한개의 프로그램만 실행되는 것 같고, 그 프로그램이 모든 시스템4 자원을 독차지 하는 것처럼 보임 ⇒ 프로세스라는 개념을 통해 가능
-
프로그램: 정적인 코드. 디스크에 저장된 실행파일
-
프로세스: 실행 중인 프로그램의 인스턴스. 여러 자원을 사용중
-
프로세스라는 객체는 실행되는 데 필요한 모든 상태정보(컨텍스트)를 가지고, 그 변화를 추적함
| 상태정보 | 설명 | 비고 |
|---|---|---|
| 프로그램 코드 | 실제 실행할 기계어 인스트럭션 (.text 영역) | 가상 메모리 공간 |
| 데이터 영역 | 전역 변수, 초기화된 데이터 등 (.data, .bss) | 가상 메모리 공간 |
| 힙 영역 | 동적 할당된 메모리 (malloc, new) | 가상 메모리 공간 |
| 스택 영역 | 함수 호출, 지역 변수 저장 | 가상 메모리 공간 |
| 레지스터 상태 | CPU에서 실행 중인 명령어 위치(PC), 변수 값 등 | CPU 내부 OR OS가 저장 |
| 파일 디스크립터 | 열려 있는 파일, 네트워크 소켓 등 | OS가 관리 (커널 공간) |
| 프로세스 상태 | 준비 상태, 실행 상태, 대기 상태 등 | OS의 PCB(Process control block) 안에 |
작동 방식: 문맥 전환(Context Switching)
- 단일 프로세서의 경우, 한 순간에 한개의 프로세스 코드만 실행 할 수있음
- 문맥전환: os가 현재 프로세스에서 다른 프로세스로 제어를 옮기려고 할 때, 현재 프로세스의 컨텍스트를 저장하고 새프로세스의 컨텍스트를 복원시키는 방법
- 문맥의 전환을 통해 프로세스는 중단된 그 상태에서부터 다시 실행될 수 있음.
작동 예시
- 프로세스A: 쉘
- 프로세스B: hello 프로세스

- 각각의 제어권이 이동함
- 운영체제(커널)로 제어권을 넘겨줄 때는 시스템 콜5을 이용
- 커널모드에서는 종료된 프로세스의 상태를 저장하고 실행할 프로세스를 선택 후 사용자 모드로 전환함
- disk interrupt: 디스크에서 메모리로 전송됐음을 의미
커널
- 커널은 별도의 프로세스가 아니다
- 프로세스를 관리하는 운영체제에 속한 별도의 코드임
- 이러한 커널이 실행되려면
- 시스템 콜이 발생하거나
- 키보드 입력과 같은 인터럽트가 발생하거나
- 프로세스 스케줄링이 필요한 경우 등
- → 커널의 실행은 프로세스 전환이 아니라, 모드 전환이자 제어권의 위임임.
쓰레드
- 프로세스를 구성하는 다수의 실행 유닛
- 쓰레드는 해당하는 프로세스의 컨텍스트에서 실행되며 동일한 코드와 전역데이터를 공유함.
- → 다수의 프로세스들보다 공유가 더 쉽다
- +) CPU는 항상 스레드 단위로 실행하고 스레드 간의 전환이 일어나는데, 그게 같은 프호세스 안의 스레드라면 가벼운 전환, 다른 프로세스의 스레드라면 문맥 전환이 되는 것임.
가상메모리

- 각 프로세스들이 메인 메모리 전체를 독점적으로 사용하고 있는 것같은 환상을 제공하는 추상화
- 각 프로세스는 가상 주소 공간이라고 하는 균일한 메모리의 모습을 가짐.
- 운영체제가 이 가상 주소공간을 실제 저장 위치(RAM, Disk)와 매핑해줌
- 구성
- 프로그램 코드/데이터:
- 코드: 모든 프로세스들이 같은 가상 주소에서 시작함.
- 데이터: 코드 다음에 전역변수와 정적변수들이 저장됨
- cf) 지역변수: 스택
- cf) 동적 할당 변수: 힙
- 힙
- 동적으로 크기가 변화함.
- 실행 중 동적으로 생성된 데이터가 저장되는 공간
- 공유라이브러리
- 중간정도 위치
- 표준 라이브러리나 수학 라이브러리같은 공유라이브러리의 코드와 데이터
- 스택
- 맨위에 위치
- 컴파일러가 함수 초룩을 구현하기 위해 사용하는 공간
- 동적으로 크기 변화
- 커널 가상메모리
- 가장 윗부분
- 커널을 위해 예약된 공간
- 응용프로그램이 읽고 쓸 수 없으며 호출도 금지됨.
- 프로그램 코드/데이터:
파일
- 모든 I/O 자원을 추상화한 공통 인터페이스
- 단순히 연속된 바이트들을 의미함
- 모든 입출력은 파일을 읽고 쓰는 형태로 이루어짐 → 유닉스 I/O라는 시스템 콜들을 이용.
| 실제 자원 | OS에서 다루는 방식 | 설명 |
|---|---|---|
| 텍스트 파일 | 일반 파일 (/home/user/note.txt) | 우리가 흔히 생각하는 그 파일 |
| 디렉토리 | 파일의 목록 파일로 취급 | 내부적으로는 메타데이터를 가진 특수 파일 |
| 터미널 | /dev/tty | 입력/출력을 읽고 쓰는 파일처럼 다룸 |
| 프린터 | /dev/lp0 | 파일처럼 열고 write()로 출력 보냄 |
| 키보드 | /dev/input/event* | 입력 이벤트가 파일처럼 흐름 |
| 소켓, 파이프 | 파일 디스크립터로 취급 | 네트워크 연결조차도 read, write 가능 |
1.8 시스템은 네트워크를 통해 다른 시스템과 통신한다
-
개별시스템의 관점에서 네트워크는 단지 또다른 입출력 장치로 볼 수 있다.
-
이메일, 메신저, 웹 페이지, FTP, telnet → 네트워크를 통해 정보를 복사하는 기능 이용
-
실행 예시
- telnet 클라이언트, “hello” 입력하고 엔터
- 클라이언트 프로그램, 입력값을 네트워크를 거쳐 telnet 서버로 보냄
- telnet 서버, 네트워크에서 문자열 받아서 원격 쉘프로그램에 전달
- 원격 쉘, hello 프로그램 실행 후 출력을 서버로 전달
- telnet 서버, 네트워크를 거쳐 출력 스트링을 telnet 클라이언트로 전달
- telnet 클라이언트 프로그램, 출력 스트링을 로컬 터미널에 표시
1.9 중요한 주제들
Amdahl의 법칙
- 한 시스템의 일부분의 성능을 개선할 때, 전체 시스템 성능에 대한 효과는 그 부분이 얼마나 중요한가와 이부분이 얼마나 빨라졌는가에 관계됨
- 전체 시스템을 상당히 빠르게 하기 위해서는 전체 시스템의 매우 큰 부분의 성능을 개선해야한다.
- 그 성능을 무시할 수 있을 정도의 시간이 걸리는 지점까지 속도를 올려도 두드러지는 성능개선이 되지 않을 수도 있다.
- ⇒ 생각보다 성능 개선이 어렵다.
동시성과 병렬성
- 컴퓨터 발전의 큰 2가지 요구: 더 많은 일, 더 빠른 실행 ⇒ 프로세서가 한번에 더 많은 일을 할 때 개선
- 동시성: 다수의 동시에 벌어지는 일을 갖은 시스템에 관한 일반적인 개념
- 병렬성: 동시성을 사용해서 시스템을 보다 빠르게 동작하도록 하는 것 → 컴퓨터 시스템의 다양한 수준의 추상화에 활용 가능
쓰레드 수준 동시성
-
한 개의 프로세스 내에서 실행되는 다수의 제어 흐름을 가질 수 있음.
-
초기: 시분할(시간 공유)을 기반으로한 시뮬레이션 형태 ⇒ 단일 프로세서 시스템
- 한 개의 컴퓨터가 실행하는 프로세스를 빠르게 전환하는 방법
- 다수의 사용자들이 한 시스템과 동시 교신 가능
- 예시: 3명의 사용자가 SSH로 접속 중
- 사용자 A가 명령어 입력 중
- 사용자 B가 코드를 컴파일 중
- 사용자 C가 파일 다운로드 중
→ OS는 이들의 프로세스를 빠르게 교체하며 CPU를 돌려줌
→ 사용자 입장에선 **“내 프로그램이 계속 실행 중”**처럼 보임
→ 실제로는 CPU가 순차적으로 처리 중
- 예시: 3명의 사용자가 SSH로 접속 중
- 한 명의 사용자가 다수의 태스크에 동시에 연관 가능
- IDE(통합 개발 환경) 같은 프로그램은 동시에:
- 코드 작성
- 실시간 오류 검사
- 백그라운드 저장
- 자동 완성
을 실행 중인데,
→ 이건 내부적으로 여러 스레드로 분리돼서 동시에 실행되는 것처럼 보이는 것이야 운영체제가 각 스레드를 빠르게 전환하며 실행함으로써
→ 사용자는 “다중 작업을 동시에 하고 있다”고 인식하게 돼
- IDE(통합 개발 환경) 같은 프로그램은 동시에:
-
멀티 프로세서 시스템
- 여러개의 프로세서를 가지고 하나의 웅영체제 제어하에 동작하는 경우
- 멀티 코어

- 여러개의 CPU를 하나의 집적화된 칩에 내장.
- 멀티 쓰레드(하이퍼 쓰레드)
- 하나의 CPU가 여러개의 제어흐름을 실행할 수 있게 해주는 기술
- 프로그램 카운터나 레지스터 파일 등 → 여러개
- 다른 부분 (e.g., 부동소수 연산기) → 한 개
- 기존에 쓰레드 간의 전환에 드는 시간이 약 2만 클럭사이클이었다면, 매싸이클마다 실행할 쓰레드를 결정할 수 있게됨.
- 다수의 태스크를 실행할 때, 동시성 시뮬레이션할 필요를 줄여줌
- 이제 CPU가 여러개라 동시에 처리할 수 있으니, 동시성처럼 보이게 시뮬레이션 할 필요가 없음
- 멀티 코어를 쓴다고 모든 프로그램이 빨라지는 것은 아님. 프로그램이 멀티 스레드 구조여야 병렬처리로 속도가 빨라질 수 있음.
- 멀티 코어: 여러 프로그램을 동시에 실행
- 멀티 쓰레드: 하나의 프로그램을 병렬 처리.
인스트럭션 수준 병렬성
- 여러개의 인스트럭션을 한번에 실행할 수 있음
- 파이프라이닝 기법, 슈퍼스케일러 프로세서 등이 여기에 해당.
싱글 인스트럭션, 다중 데이터 병렬성(SIMD)
- 한개의 인스트럭션이 병렬로 다수의 연산을 수행할 수 있는 특수 하드웨어.
- 영상, 소리, 동영상 데이터 처리 및 머신러닝 분야에서 많이 사용됨.
- (여러 개의 연산을 숨기고, 사용자에겐 “하나의 명령처럼 보이게” 만드는 추상화)
추가적인 추상화
- ISA:
- 실제 프로세서 하드웨어의 추상화
- 마치 한번에 하나의 인스트럭션을 실행하는 프로세서인 것처럼 보이게 함.
- 실제로는 파이프라이닝, out-of-order, 분기 예측, 병렬 유닛 등 뭐가 많지만, 신경 쓰지 않아도됨
- 가상머신
- 운영체제, 프로세서, 프로그램 모두를 포함하는 컴퓨터 전체의 추상화를 제공.
- 하드웨어가 실제로 존재하지 않아도 있는 것처럼 “흉내 내는” 소프트웨어 컴퓨터
- 운영체제, CPU, 메모리, 저장공간, 프로그램 실행 환경까지 모두 가짜로 만든 컴퓨터 환경