운영체제란?
운영체제(OS, Operating System): 사용자의 하드웨어, 시스템 리소스를 제어하고 프로그램에 대한 일반적 서비스를 지원하는 시스템 소프트웨어이다. 간단하게 말하자면, 컴퓨터를 쉽게 다룰 수 있게 해주는 인터페이스
ex) 윈도우, macOS, 리눅스
운영체제는 하드웨어와 소프트웨어를 관리하는 소프트웨어 전체라고 할 수 있다. 주요 목적은 하드웨어를 추상화하여 응용 프로그램이 하드웨어의 복잡한 부분을 직접 다루지 않도록 하고, 자원을 효율적으로 할당하여 시스템 전반의 성능을 최적화하는 것이다.
운영체제의 주요 기능과 역할을 다음과 같다.
- 프로세스 관리 (Process Management): 프로세스는 실행 중인 프로그램을 나타내며, 운영체제는 프로세스의 생성, 스케줄링, 종료 등을 관리한다.
- 메모리 관리 (Memory Management): 시스템의 메모리를 효과적으로 할당하고 관리하여 여러 프로세스가 동시에 실행될 수 있도록 한다.
- 파일 시스템 관리 (File System Management): 파일을 생성, 읽기, 쓰기, 삭제하고 파일의 구조를 관리하여 데이터를 저장하고 검색할 수 있도록 한다.
- 입출력 관리 (I/O Management): 입출력 장치와의 상호 작용을 관리하며, 효율적인 데이터 전송을 지원한다.
- 장치 드라이버 관리 (Device Driver Management): 하드웨어와 통신하기 위한 드라이버를 관리하고 제공한다.
- 보안 및 권한 관리 (Security and Authorization Management): 시스템 자원에 대한 접근 권한을 관리하고, 보안 정책을 시행하여 시스템을 안전하게 유지한다.
- 네트워킹 (Networking): 네트워크 기능을 제공하여 여러 컴퓨터 간에 통신을 가능케 한다.
- 시스템 호출 인터페이스 (System Call Interface): 응용 프로그램이 운영체제의 서비스를 사용할 수 있도록 하는 인터페이스를 제공합니다.
운영체제의 구성요소
하드웨어 위에 커널이 올라가고, 커널 위에서 셸과 애플리케이션이 실행된다. 사용자는 기본적으로 셸을 통해 애플리케이션을 실행한다.
커널
커널은 운영체제의 핵심 부분으로, 하드웨어와 응용 프로그램 간의 상호 작용을 관리한다. 프로세스 관리, 메모리 관리, 입출력 관리, 파일 시스템 등과 같은 기본적인 운영체제 기능을 수행한다. 하드웨어와 응용 프로그램 사이에서 인터페이스를 제공하는 역할을 하며 컴퓨터 자원들을 관리하는 역할을 한다.
부트 로더
컴퓨터를 시작할 때, 부트로더는 운영체제를 로드하고 실행하는 역할을 한다. 보통은 시스템의 BIOS 또는 UEFI에 의해 호출되어, 하드 디스크 또는 다른 저장 장치에 있는 운영체제를 메모리로 로드한다.
셸
셸은 사용자와 운영체제 간의 상호 작용을 제공하는 인터페이스 역할을 한다. 사용자는 명령어를 입력하여 셸을 통해 운영체제에 명령을 내릴 수 있다. 셸은 명령어 해석 및 실행을 담당한다.
디바이스 드라이버
하드웨어와 상호 작용하기 위한 드라이버들이 포함된다. 이들은 특정 하드웨어와 통신하여 하드웨어를 운영체제에서 인식하고 사용할 수 있도록 한다.
파일 시스템 (File System)
데이터를 저장하고 관리하기 위한 파일과 디렉토리 구조를 제공합니다. 파일 시스템은 데이터의 저장, 검색, 수정, 삭제를 관리합니다.
미들웨어: 운영체제의 구성요소는 아니지만, 운영체제와 응용 프로그램 간의 인터페이스 역할을 수행하는 중간 소프트웨어 계층이다. 일반적으로 운영체제와 응용 프로그램 사이에서 통신과 상호 작용을 촉진하는 역할을 한다. 미들웨어는 운영체제 위에서 동작하며 분산 환경에서 특히 유용하게 사용된다.
펌웨어: 일반적으로 하드웨어에 내장되어 있는 소프트웨어로, 공장 출고 시에 설치되며 일반적으로 사용자가 직접 수정할 수 없다.
프로세스와 스레드
프로세스(Process) : 실행 중인 프로그램의 인스턴스로, 메모리에 할당된 코드, 데이터, 시스템 리소스, 스레드 등을 포함한다. 쉽게 말해 컴퓨터에서 실행중인 프로그램이다.
각 프로세스는 독립적인 실행 환결을 가지며, 하나의 프로세스가 다른 프로세스에 영향을 미치지 않는다. 프로세스 간 통신은 주로 IPC(Inter-Process Communication)을 통해 이루어진다. 예를 들어, 파일이나 소켓을 사용하여 데이터를 공유할 수 있다. IPC외에도 LPC(Local Inter-Process Communication, Windows OS에서 지원)을 통해서도 통신할 수 있다. 각 프로세스는 운영체제에 의해 별도의 메모리 공간과 자원이 할당되어 실행된다. 메모리 영역은 코드 영역, 데이터 영역, 스택 영역, 힙 영역 이렇게 4가지로 나뉘어 이루어져 있다.
스레드(Thread): 프로세스 내에서 실행되는 작은 작업 단위로, 프로세스의 자원을 공유한다. 한 프로세스 내에서 여러 개의 스레드가 동시에 실행될 수 있다.
같은 프로세스 내의 다른 스레드와 메모리 공간을 공유하므로, 데이터를 효율적으로 공유할 수 있다. 프로세스에 비해 경량화되어 있어, 스레드 간 전환 및 생성이 프로세스에 비해 빠르다. 스레드 간 통신은 공유 변수 등을 통해 직접 이루어질 수 있다. 스레드는 종속성이 있을 수 있어, 한 스레드의 오류가 다른 스레드에 영향을 미칠 수 있다. 스레드는 동시에 실행되므로, 병렬 처리와 동시성을 구현하는 데 사용된다. 스레드는 만들어질 때마다 스택영역을 할당받는다.
쉽게 생각하면 프로세스는 일터, 스레드는 직원이다.
병렬 처리(Parallel Processing): 여러 작업이 동시에 진행되는 것을 의미한다. 여러 프로세스 또는 코어를 사용하여 동시에 여러 작업을 처리함으로써 성능을 향상시키는 것이 목적이다. (하드웨어 측면 성능 향상)
동시성(Concurrency): 동시성은 여러 작업이 동시에 진행되는 것처럼 보이는 것을 나타낸다. 실제로 동시에 실행되는 것은 아니지만, 작업 간에 전환을 통해 빠르게 번갈아 가며 진행된다. (소프트웨어 측면 향상)
프로세스와 스레드의 생명주기
프로세스의 생명주기
프로세스의 생명주기는 프로세스가 생성되어서 완료될 때까지의 전반적인 생명 주기를 의미한다. 전형적인 프로세스의 상태주기는 여러 가지 상태로 나뉘어진다.
1. 생성 상태(New)
- 프로레스가 생성되었지만 아직 실행되지 않은 초기상태
- 프로레스 제어 블록(PCB)이 생성되고 초기화된다.
2. 준비 상태(Ready)
- 프로세스가 CPU를 할당받을 준비가 되어 있지만 아직 CPU를 할당받지 못한 상태
- 프로세스가 CPU를 기다리는 대기 큐에 들어가 있는 상태
3. 실행 상태(Running)
- CPU를 할당받아 명령어를 실행하는 상태
- 현재 실행 중인 프로세스가 있을 때만 해당 상태가 존재한다.
4. 차단(대기) 상태(Blocked/Waiting)
- 특정 이벤트가 발생하거나, 입출력 작업을 기다리는 동안, 혹은 특정 자원을 기다리는 동안에 프로세스는 차단 상태로 전환
- 차단된 프로세스는 대기 큐에 들어가며, 이벤트가 발생하면 준비 상태로 전환
5. 종료 상태(Terminated)
- 프로세스가 실행을 완료하거나, 강제로 종료되었을 때의 상태
- 자원이 반환되고 PCB는 제거된다.
PCB(프로세스 제어 블록, Process Control Block)
: 운영체제가 각 프로세스를 관리하기 위해 사용하는 데이터 구조이다. PCB는 프로세스의 현재 상태와 정보를 저장하며, 프로세스가 CPU에서 실행될 때 필요한 모든 정보를 유지한다. PCB는 각 프로세스마다 하나씩 할당되며 프로세스의 상태를 추적하고 제어하는데 사용된다. 운영 체제 스케줄러가 프로세스 간 전환을 수행할 때 사용한다.
프로세스는 이러한 상태들을 전이하면서 실행된다. 일반적으로, 프로세스의 상태 전이는 다음과 같이 일어날 수 있다.
- Admitted(생성 -> 준비): 프로세스가 생성되면 준비 상태로 이동한다.
- Dispatch(준비 -> 실행): 준비 상태의 프로세스가 CPU를 할당받아 스케줄러에 의해 실행 상태로 이동한다.
- Interrupt(실행 -> 준비): 실행 중인 프로세스가 중단되어 준비 상태로 돌아가는 상태로, 예를 들면 타이머 인터럽트 등의 이벤트가 발생할 때 발생한다.
- I/O or event wait (실행 -> 대기): 프로세스가 입출력 작업이나 이벤트 발생을 기다리는 동안 대기 상태로 이동한다.
- I/O or event completion (대기 -> 준비): 대기 중이던 프로세스가 기다리던 이벤트가 발생하면 준비 상태로 이동한다.
- Exit(실행 -> 종료): 프로세스가 실행을 완료하면 종료 상태로 이동한다.
컨텍스트 스위칭(Context Switching)
: 현재 실행 중인 프로세스나 스레드의 상태를 저장하고, 다음으로 실행할 프로세스나 스레드의 상태를 불러오는 과정을 의미한다. 이는 CPU를 여러 프로세스나 스레드사이에서 전환하여 동시에 여러 작업을 수행할 수 있도록 하는 기술이다.
간단하게 말하면, 컨텍스트 스위칭은 하나의 작업이 실행 중일 때 다른 작업으로 전환하는 과정으로, 운영 체제의 스케줄러가 관리한다.
컨텍스트 스위칭 오버헤드
: 실행중인 프로세스나 스레드의 상태를 저장하고, 다음으로 실행할 프로세스나 스레드의 상태를 복원하는 작업에 소요되는 시간과 자원의 비용을 의미한다. 대체로 레지스터 값 저장 및 복원, 메모리 상태 저장 및 복원, 캐시 플러시 및 로드, 시스템 호출 및 인터럽트 처리, 프로세서 캐시 미스인 상황에서 발생할 수 있다.
스레드의 생명주기
스레드의 생명주기는 스레드가 생성되어서 종료될 때까지의 상태를 나타낸다. 일반적으로 스레드는 여러 상태 간을 전환하며 실행된다.
1. 생성 상태 (New):
- 스레드가 생성되었지만 아직 실행되기 전의 초기 상태
- Thread 클래스의 인스턴스를 생성하고 start() 메서드를 호출하여 스레드를 시작하면 생성 상태에서 실행 상태로 전환된다.
2. 실행 상태 (Runnable):
- 스레드가 실행할 수 있는 상태
- start() 메서드를 호출하면 스레드는 실행 상태로 이동하며, 스케줄러에 의해 CPU를 할당받을 때까지 대기한다.
3. 대기 또는 차단 상태 (Blocked):
- 스레드가 어떤 이벤트를 기다리거나, 임계 영역에 진입을 시도하였으나 실패하여 차단된 상태
- 이벤트가 발생하면 대기 상태에서 실행 상태로 전환된다.
4. 종료 상태 (Terminated):
- 스레드가 실행을 완료하거나 강제로 종료되었을 때의 상태이다.
- run() 메서드의 실행이 종료되면 종료 상태로 전환된다.
스레드는 이러한 상태들을 전환하면서 실행되며, 상태 전이는 다양한 이벤트와 조건에 의해 발생한다. 스레드 생명주기는 프로그램의 동시성을 관리하고, 스레드 간의 상호 작용을 조절하는 데 중요한 역할을 한다.
TCB(Thread Control Block): 스레드 또는 프로세스의 상태를 관리하는 중요한 자료구조. 해당 스레드 또는 프로세스에 대한 정보를 저장하고, 스케줄러가 스레드를 관리하는 데 사용된다.
스레드 컨텍스트 스위칭: 현재 실행 중인 스레드에서 다른 스레드로 제어를 전환하는 과정
프로세스와 스레드의 스케줄링
프로세스 스케줄링
프로세스 스케줄링: 운영체제에서 여러 프로세스가 CPU를 사용하는 순서를 결정하는 작업. 이는 시스템의 자원을 효율적으로 사용하고, 프로세스들 간의 공정한 실행을 유지하기 위해 필요하다.
주요 프로세스 스케줄링 알고리즘은 다음과 같다.
- FCFS (First-Come-First-Served):
- 먼저 도착한 프로세스가 먼저 CPU를 할당받는 방식
- 간단하고 공정한 방법이지만, 평균 대기 시간이나 응답 시간 면에서 효율성이 낮을 수 있다
- SJF (Shortest Job First):
- 예상 실행 시간이 가장 짧은 프로세스를 먼저 실행하는 방식
- 실행 시간을 정확하게 예측해야 하므로 예측이 어려운 경우에는 사용이 어려울 수 있다
- Round Robin:
- 각 프로세스에 일정 시간(타임 슬라이스 또는 양자)을 할당하고, 시간이 다 되면 다음 프로세스로 전환하는 방식
- 시분할 시스템에서 많이 사용되며, 모든 프로세스가 공평한 기회를 가진다.
- Priority Scheduling:
- 각 프로세스에 우선순위를 부여하고, 높은 우선순위를 가진 프로세스에게 CPU를 할당하는 방식
- 우선순위가 낮은 프로세스가 계속해서 무시되는 "스타벅스 효과"가 발생할 수 있다.
- Multilevel Queue Scheduling:
- 여러 개의 큐를 사용하여 각 큐에는 다른 우선순위의 프로세스를 배치하고, 각 큐 사이에 스케줄링을 적용하는 방식
- 다양한 우선순위의 프로세스를 다룰 수 있으며, 시스템의 특성에 따라 다양한 큐를 설정할 수 있다.
선점 스케줄링 VS 비선점 스케줄링
- 선점 스케줄링 (Preemptive Scheduling):
- 이 방식에서는 실행 중인 프로세스가 다른 프로세스에 의해 강제로 중단되고, CPU를 다른 프로세스에게 할당할 수 있다. 어떤 프로세스가 실행 중에 다른 프로세스가 더 중요하거나 우선순위가 높으면 실행 중인 프로세스가 강제로 중단되고 높은 우선순위의 프로세스가 실행된다.
- 우선순위가 높은 작업이 빠르게 처리되어야 할 때 유용하며, 프로세스 간의 경쟁이나 우선순위 변화에 대응할 수 있습니다.
- ex) Round Robin 스케줄링, Priority Scheduling 등
- 비선점 스케줄링 (Non-preemptive Scheduling):
- 이 방식에서는 한 프로세스가 CPU를 점유하고 있을 때 다른 프로세스가 강제로 그 CPU를 빼앗을 수 없다. 현재 실행 중인 프로세스가 종료하거나 입출력 요청 등의 이벤트가 발생해야만 CPU를 양도한다.
- 선점 스케줄링에 비해 구현이 간단하며, 일관된 실행 환경을 제공합니다. 하지만 실시간 시스템에서는 불리할 수 있습니다.
- 콘보이 효과가 발생할 수 있다. 콘보이 효과란? CPU를 오래 사용하는 프로세스가 도착하게 되면, 다른 프로세스가 CPU를 사용하는데 기다리는 대기 시간이 커지는 현상을 말한다.
- ex) First Come First Serve (FCFS), Shortest Job Next (SJN), Priority Scheduling 등
스레드의 스케줄링
스레드 스케줄링:여러 스레드 중에서 어떤 스레드가 CPU를 사용할지를 결정하는 과정. 이는 다중 프로세서 시스템 또는 멀티코어 시스템에서 더욱 중요하며, 여러 스레드가 경쟁적으로 CPU 자원을 얻기 위해 경쟁하는 경우가 많다.
- Round Robin (라운드 로빈):
- 각 스레드에 일정한 시간(타임 슬라이스)을 할당하고, 해당 시간이 지나면 다음 스레드로 CPU를 전환하는 방식
- 공정한 스케줄링을 제공하지만, 각 스레드에게 일정한 시간을 부여하기 때문에 일부 스레드가 CPU를 낭비할 수 있다.
- Priority Scheduling (우선순위 스케줄링):
- 각 스레드에 우선순위를 부여하고, 높은 우선순위를 가진 스레드에게 CPU를 할당하는 방식
- 우선순위가 낮은 스레드가 계속해서 무시될 수 있는 "스타벅스 효과"가 발생할 수 있다.
- Multilevel Queue Scheduling (다단계 큐 스케줄링):
- 여러 개의 큐를 사용하여 각 큐에는 다른 우선순위의 스레드를 배치하고, 각 큐 사이에 스케줄링을 적용하는 방식
- 다양한 우선순위의 스레드를 다룰 수 있으며, 시스템의 특성에 따라 다양한 큐를 설정할 수 있다
- Multilevel Feedback Queue Scheduling (다단계 피드백 큐 스케줄링):
- 다단계 큐 스케줄링에서 발전한 형태로, 스레드가 자주 CPU를 사용하면 우선순위를 낮추고, 자주 대기하면 우선순위를 높이는 방식
- 스레드의 동적인 특성에 따라 우선순위를 조절하여 효율적인 스케줄링을 제공한다.
비동기식 병행 실행
비동기식 병행 실행: 여러 작업이 동시에 진행되는 실행 모델. 이러한 작업은 서로 독립적이거나, 작은 단위로 분할되어 병렬 또는 동시에 실행된다. 이는 일반적으로 병렬 처리, 이벤트 기반 프로그래밍, 비동기 프로그래밍과 관련이 있다.
스레드를 공부했다면, 동기화 문제에 대해서 한번 쯤은 들어봤을 것이다. 비동기식 병행 실행 중인 상태에서 여러 스레드가 공유된 자원에 동시에 접근하려고 할 때 발생하는 문제이다. 이로인해 예측할 수 없는 결과, 데이터 일관성 문제, 경쟁 상태 등이 발생할 수 있다.
경쟁상태
경쟁 상태(Race Condition): 둘 이상의 스레드 또는 프로세스가 공유된 자원에 동시에 접근하려고 할 때 발생하는 상황을 의미한다. 이러한 상황에서 예측할 수 없는 결과가 발생할 수 있으며, 프로그램의 정확성을 위협할 수 있다.
경쟁 상태는 다음과 같은 상황에서 발생한다.
- 공유된 자원의 동시 접근:
- 둘 이상의 스레드나 프로세스가 공유된 변수, 자료 구조, 파일 등의 자원에 동시에 접근하려고 하는 경우 발생한다.
- 동시성 제어 없는 연산:
- 여러 스레드가 동시에 공유된 변수를 변경하는 연산을 수행할 때, 연산의 실행 순서에 따라 결과가 달라질 수 있다.
- 인터리빙(Interleaving):
- 여러 스레드가 번갈아 가며 실행되는 동안, 각 스레드가 공유 자원을 읽거나 쓰는 연산이 서로 교차되면서 예측할 수 없는 상태가 발생한다.
- 순서 보장의 부재:
- 동시에 실행되는 스레드 간에 실행 순서를 보장하지 않는 경우, 각 스레드가 자원을 변경하는 순서에 따라 결과가 달라질 수 있다.
경쟁 상태를 해결하기 위해선 상호배제(Mutual Exclusion) 메커니즘을 사용하여 하나의 스레드만이 특정 시점에 공유 자원에 접근하도록 보장해야한다.
임계영역
임계 영역(Critical Section): 여러 스레드 또는 프로세스가 공유된 자원에 접근하는 부분을 나타낸다. 즉, 독점을 보장하는 영역이다.
- 공유 자원 접근:
- 임계 영역은 하나의 스레드가 공유 자원을 읽거나 쓰는 부분이다. 다수의 스레드가 동시에 임계 영역에 접근하면 문제가 발생할 수 있으므로, 상호배제(Mutual Exclusion)가 필요하다.
- 동기화 필요:
- 여러 스레드가 동시에 임계 영역에 접근할 때, 동기화 메커니즘이 필요하다. 이를 통해 하나의 스레드가 임계 영역에 들어가 있는 동안 다른 스레드들은 기다려야 한다.
- 원자성(Atomicity) 보장:
- 임계 영역에서의 연산은 원자적으로 실행되어야 한다. 이는 연산이 중간에 중단되거나 다른 스레드에 의해 간섭을 받지 않아야 함을 의미한다.
- 데이터 일관성 유지:
- 임계 영역에서의 데이터 변경은 일관성이 유지되어야 한. 여러 스레드가 동시에 자원을 변경하면 데이터 일관성이 깨질 수 있다.
교착 상태(Dead Lock): 둘 이상의 프로세스가 다른 프로세스가 점유하고 있는 자원을 서로 기다릴 때 무한 대기에 빠지는 상황. 교착 상태가 발생하면 모든 프로세스나 스레드가 대기 상태에 빠져 더 이상 진행할 수 없게 되며, 시스템이 불안정한 상태에 빠진. 이를 방지하기 위해서는 교착 상태를 해결하는 메커니즘이 필요하다.
발생 조건: 상호배제, 점유대기, 비선점, 순환대기
회피 기법: 은행원 알고리즘
상호배제
상호배제(Mutual Exclusion): 여러 프로세스나 스레드가 공유된 자원에 동시에 접근하는 것을 방지하는 메커니즘을 의미한다. 상호배제는 한 시점에서 오직 하나의 프로세스나 스레드만이 공유 자원을 사용하도록 보장함으로써, 데이터 일관성과 안정성을 유지하는 것이 중요하다.
상호배제를 구현하기 위한 대표적인 방법으로는 뮤텍스(Mutex)와 세마포어(Semaphore)가 있다.
- 뮤텍스(Mutex):
- 뮤텍스는 상호배제를 달성하기 위한 동기화 기법 중 하나이다.
- 뮤텍스는 임계 영역에 진입하는 것을 허용하는 토큰같은 것이다.
- 뮤텍스는 두가지 상태를 가진다. -> 잠겨진(Locked) 상태와 잠금이 해제된(Unlocked) 상태.
- 한 스레드가 임계 영역에 진입하면 뮤텍스를 잠그고, 다른 스레드가 이 영역에 진입하려면 뮤텍스를 얻을 때까지 대기한다.
- 세마포어(Semaphore):
- 세마포어는 정수 변수를 사용하여 동시에 여러 스레드가 임계 영역에 진입하는 것을 허용하거나 제한한다.
- 세마포어 값이 1이면 상호배제를 구현한 뮤텍스와 동일한 역할을 수행하며, 값이 N보다 크면 최대 N개의 스레드가 동시에 임계 영역에 접근할 수 있다.
- 1개면 이진 세마포어, 2개 이상의 경우에는 카운팅 세마포어라고 부른다.
- 모니터(Monitor):
- 하나의 프로세스 내의 다른 스레드 간의 동기화에 사용된다.
- 모니터는 프레임워크나 라이브러리 그 자체에서 제공된다.
- 일련의 동기화 작업들이 캡슐화되어 있어 synchronized, wait(), notify() 등의 키워드를 통해 편하게 동기화 할 수 있다.
메모리 관리
가상 메모리와 물리 메모리
가상 메모리(Virtual Memory): 물리 메모리를 보조하기 위해 사용되는 개념으로, 주로 하드 디스크와 같은 보조 기억 장치를 활용한다. 가상 메모리는 프로세스에게 실제 메모리보다 큰 주소 공간을 제공하여 물리 메모리가 부족한 경우에도 프로세스가 실행될 수 있도록 한다.
물리 메모리(Physical Memory):컴퓨터의 실제 하드웨어에 존재하는 메모리를 나타낸다. 이는 RAM(Random Access Memory)이라고도 불리며, 프로세서가 직접 접근하여 데이터를 읽고 쓸 수 있는 메모리이다.
논리적 주소 (Logical Address):프로세스가 생성하는 주소로, 프로세스가 실제로 사용하는 주소이다. 이 주소는 프로세스가 자신의 코드나 데이터에 접근할 때 사용된다. 가상 메모리 상에서 사용되며, 프로세스는 이 주소를 통해 메모리에 접근한다. 가상 메모리는 보조 기억장치(주로 하드 디스크)와 물리 메모리 간의 매핑을 담당하며, 이를 통해 프로세스는 논리적 주소를 사용하면서도 물리적 메모리에 액세스한다.
물리적 주소(Physical Address): 실제 하드웨어 메모리에 대응하는 주소로, RAM(물리 메모리)에서 직접적으로 읽고 쓸 수 있는 주소이다. 논리적 주소와 물리적 주소 간의 변환은 메모리 관리 단위(MMU, Memory Management Unit) 등의 하드웨어나 운영체제에 의해 수행된다.
주소 바인딩
- 컴파일 타임 바인딩(Compile-Time Binding):
- 프로그램이 컴파일될 때 논리적 주소가 물리적 주소로 변환되어 메모리에 할당된다. 이 방식은 실행 중에 주소의 변화가 없으며, 실행 파일이 메모리에 로드될 때 이미 주소가 고정되어 있다.
- 로드 타임 바인딩(Load-Time Binding):
- 프로그램이 로드될 때 논리적 주소가 물리적 주소로 변환되어 메모리에 할당된다. 실행 파일이 메모리에 로드되는 동안 주소를 결정하며, 주소가 고정된다.
- 실행 타임 바인딩(Runtime Binding):
- 프로그램이 실행 중일 때 논리적 주소가 물리적 주소로 동적으로 변환된다. 이 방식은 가상 메모리와 관련이 있으며, 프로세스 실행 도중 메모리의 어느 위치에 어떤 데이터가 위치하는지가 결정된다.
메모리 단편화
메모리 단편화(Memory Fragmentation): 메모리 공간이 조각화되어, 프로세스에게 할당할 충분한 연속된 메모리 공간을 찾기 어려워지는 현상을 나타낸다.
메모리 단편화는 크게 외부 단편화와 내부 단편화로 나뉜다.
- 외부 단편화(External Fragmentation):
- 할당되지 않은 작은 조각들이 메모리 주소 공간에 흩어져 있어, 이를 합치더라도 충분한 크기의 연속된 공간을 만들어 낼 수 없는 상황을 의미한다.
- 프로세스는 필요한 메모리 양이 연속된 블록으로 할당되어야 하는데, 외부 단편화로 인해 충분한 크기의 연속된 공간을 찾기 어려워진다.
- 내부 단편화(Internal Fragmentation):
- 메모리 할당 시에 프로세스가 요구하는 메모리보다 조금 더 많은 메모리가 할당되어, 실제로 사용하지 않는 부분이 발생하는 경우를 의미한다.
- 주로 고정된 크기의 메모리 블록을 사용하는 시스템에서 발생하며, 할당된 메모리 중 일부가 사용되지 않고 낭비되는 상황을 나타낸다.
단편화 해결 방법
- 압축(Compaction):
- 분산된 메모리 공간을 재배치하여 단편화를 감소시킨다.
- 메모리 공간들을 재배치하여 단편화로 인해 분산되어 있는 메모리 공간을 합친다.
- 주로 동적 메모리 할당 및 해제가 빈번한 상황에서 사용된다.
- 통합(Coalescing):
- 외부 단편화를 줄이기 위한 기법으로, 분산된 메모리 공간 중에서 인접해 있는 것들을 합치는 방법
- 분산된 메모리 공간 중에서 인접해 있는 영역을 합쳐서 하나의 큰 공간으로 만든다.
- 페이징(Paging):
- 외부 단편화를 해결하기 위한 가상 메모리 기법으로, 일정한 크기의 페이지로 메모리를 나누어 사용한다.
- 프로세스를 일정한 크기의 페이지로 나누고, 페이지 단위로 주기억장치에 할당하여 외부 단편화를 최소화한다.
- 페이지는 고정된 크기를 가지며, 페이지 테이블을 통해 논리 주소를 물리 주소로 변환한다.
- 세그멘테이션(Segmentation):
- 내부 단편화를 줄이기 위한 가상 메모리 기법으로, 서로 다른 크기의 세그먼트로 메모리를 나누어 사용한다.
- 프로세스를 서로 다른 크기의 세그먼트로 나누어 메모리에 할당하여 내부 단편화를 최소화한다.
- 각 세그먼트는 논리적인 블록을 나타내며, 세그먼트 테이블을 통해 논리 주소를 물리 주소로 변환한다.
- 메모리 풀(Memory Pool):
- 내부 및 외부 단편화를 해결하기 위한 기법으로, 메모리를 사용자가 직접 지정한 크기로 미리 할당받아 사용한다.
- 사용자가 필요로 하는 크기의 메모리 블록을 미리 할당받아 풀에 보관하고, 필요할 때마다 풀에서 할당하여 사용한다.
- 동적 할당 및 해제가 빈번한 상황에서 사용되며, 메모리 낭비를 최소화한다.
'CS' 카테고리의 다른 글
[네트워크] 네트워크 개념 정리 (1) | 2023.12.01 |
---|