3.3.1 프로세스와 컴파일 과정
*프로그램을 만드는 과정은 언어마다 다름.
실행 파일을 실행 → 프로세스

1. 전처리 (Preprocessor)
- 역할: 소스 코드를 컴파일하기 전에 특정 작업을 수행하는 단계
- 주요 작업:
- 매크로 처리: #define으로 정의된 매크로를 치환.
- 헤더 파일 포함: #include 지시문 처리.
- 조건부 컴파일: #ifdef, #ifndef 등의 조건문 처리.
- 결과: 전처리가 끝난 코드는 컴파일러에 전달되어 실제 컴파일 작업 진행
2. 컴파일러 (Compiler)
- 역할: 고급 언어(C++와 같은)를 저급 언어(어셈블리 코드나 기계어)로 변환.
- 주요 작업:
- 구문 분석: 소스 코드의 문법적 오류 검출.
- 중간 코드 생성: 최적화 가능한 중간 표현 생성.
- 최적화: 실행 속도 향상 및 메모리 사용 최적화.
- 어셈블리 코드 생성: 저수준의 어셈블리 코드로 변환.
- 결과: 어셈블러가 이해할 수 있는 어셈블리 코드 생성
3. 어셈블러 (Assembler)
- 역할: 어셈블리 코드를 기계어(바이너리 코드)로 변환.
- 주요 작업:
- 어셈블리 코드의 명령어를 CPU가 실행할 수 있는 이진 형식으로 변환.
- 결과: 개별 오브젝트 파일(.obj 또는 .o) 생성.
4. 링커 (Linker)
- 역할: 여러 개의 오브젝트 파일(.obj 또는 .o)을 연결하여 실행 파일(.exe 또는 .out)을 생성.
- 주요 작업:
- 외부 심볼 참조 해결: 서로 다른 파일의 함수나 변수 연결.
- 라이브러리 연결: 표준 라이브러리 및 사용자 정의 라이브러리 추가.
- 실행 가능한 파일 생성.
- 결과: 실행 가능한 최종 프로그램 생성
정적 라이브러리와 동적 라이브러리의 차이
항목 | 정적 라이브러리 (Static Library) | 동적 라이브러리 (Dynamic Library) |
정의 | 라이브러리 코드가 실행 파일에 포함됨 | 런타임에 별도로 로드되는 라이브러리 |
확장자 | Windows: .lib / Linux: .a | Windows: .dll / Linux: .so |
크기 | 실행 파일 크기가 커짐 | 실행 파일 크기가 작음 |
성능 | 실행 속도가 빠름 (라이브러리 로드 시간이 없음) | 런타임에 라이브러리를 로드해야 하므로 상대적으로 느림 |
배포 | 단일 실행 파일로 배포 가능 | 라이브러리 파일과 함께 배포 필요 |
재사용성 | 다른 프로그램과 코드 재사용이 어려움 | 여러 프로그램이 동일 라이브러리를 공유 가능 |
업데이트 | 실행 파일을 다시 컴파일해야 업데이트 가능 | 라이브러리 파일만 교체하면 업데이트 가능 |
종속성 문제 | 종속성 문제가 없음 | 종속 라이브러리가 없으면 실행 불가 |
디버깅 | 코드 디버깅이 쉽고 독립적 | 디버깅이 복잡할 수 있음 |
호환성 | OS/컴파일러 간 호환성 낮음 | OS/컴파일러 간 호환성 높음 |
3.3.2 프로세스의 상태

0. 프로세스 생성
- fork()와 exec()는 프로세스 생성과 관련된 두 가지 중요한 시스템 콜
- 유닉스 기반 시스템에서 새로운 프로세스를 생성, 실행
1. fork()
- 정의: 현재 실행 중인 프로세스를 복제하여 새 프로세스를 생성하는 시스템 호출.
- 특징:
- 부모 프로세스를 복사하여 자식 프로세스를 생성.
- 자식 프로세스는 부모 프로세스의 모든 메모리 공간, 파일 디스크립터, 변수 등을 복사.
- 부모 프로세스와 자식 프로세스는 독립적으로 실행됨.
- fork()는 호출 시 두 번 반환:
- 부모 프로세스: 자식 프로세스의 PID 반환.
- 자식 프로세스: 0 반환.
2. exec()
- 정의: 현재 프로세스의 메모리 공간을 새로운 프로그램으로 교체하는 시스템 호출.
- 특징:
- exec() 호출 이후, 기존 프로세스의 메모리와 실행 상태가 완전히 교체됨.
- 프로세스 ID는 유지되지만, 새로운 프로그램으로 실행.
- 여러 변형 함수 제공 (execl, execv, execle, execvp, execve 등):
- 프로그램 실행 방식에 따라 매개변수와 환경 변수 전달 가능.
항목 | fork() | exec() | 함께 사용하는 경우 |
역할 | 프로세스를 복제하여 새로운 자식 프로세스 생성 | 현재 프로세스를 새로운 프로그램으로 교체 | 부모-자식 프로세스를 활용해 새로운 프로그램 실행 |
결과 | 부모와 자식 프로세스가 독립적으로 실행됨 | 기존 프로세스가 새로운 프로그램으로 교체됨 | 자식 프로세스는 새로운 프로그램 실행, 부모는 기존 작업 유지 |
독립적 사용 가능 여부 | 가능 | 가능 | 함께 사용하는 것이 일반적 |
주 사용 사례 | 병렬 작업, 멀티 프로세싱 구현 | 현재 프로세스를 다른 프로그램으로 대체 | 부모-자식 프로세스 구조를 활용한 새로운 프로그램 실행 |
장점 | 부모와 동일한 프로세스를 간단히 복제 | 새로운 프로그램을 실행하기에 적합 | 부모 프로세스를 유지하면서 새로운 작업을 실행 가능 |
단점 | 메모리 복제로 인한 자원 낭비 가능 | 기존 프로세스 상태가 완전히 사라짐 | 두 시스템 호출을 사용해야 하므로 구현이 복잡해질 수 있음 |
예시 | 병렬 데이터 처리, 서버 클라이언트 요청 처리 | 쉘에서 특정 명령 실행 | 웹 서버가 클라이언트 요청마다 새로운 작업을 처리하는 경우 |
1. 대기 상태 (Ready State)
- 정의: 프로세스가 실행을 위해 준비된 상태.
- 특징:
- CPU를 사용할 수 있기를 기다리는 상태입니다.
- 프로세스는 메모리와 필요한 자원을 이미 할당받았으나, CPU 스케줄러에 의해 CPU 할당을 기다립니다.
- 여러 프로세스가 대기 큐에 있을 수 있습니다.
- 예시:
- 다중 프로세싱 환경에서 여러 작업이 동시에 실행 대기 중인 경우.
2. 대기 중단 상태 (Waiting State)
- 정의: 프로세스가 특정 이벤트나 자원의 준비가 완료되기를 기다리는 상태.
- 특징:
- I/O 작업(파일 읽기/쓰기, 사용자 입력 등)과 같은 자원 대기 시 발생합니다.
- 프로세스는 CPU를 점유하지 않고 대기 큐에서 이벤트가 발생하기를 기다립니다.
- 예시:
- 디스크에서 데이터를 읽는 동안 프로세스가 대기.
3. 실행 상태 (Running State)
- 정의: 프로세스가 CPU에서 실행 중인 상태.
- 특징:
- CPU 스케줄러에 의해 CPU를 할당받은 프로세스만 실행 상태가 됩니다.
- 단일 CPU 시스템에서는 동시에 하나의 프로세스만 실행 상태일 수 있습니다.
- 예시:
- 프로그램이 현재 실행되고 있는 순간.
4. 중단 상태 (Blocked State)
- 정의: 프로세스가 실행될 수 없는 상태로, 특정 조건이 충족될 때까지 대기해야 함.
- 특징:
- 자원의 부족이나 특정 조건 미충족으로 인해 중단된 상태.
- 프로세스는 실행 가능한 상태가 아니며, 대기 상태로 돌아갈 수 없습니다.
- 예시:
- 네트워크 연결 실패로 인해 작업이 중단된 경우.
5. 일시 중단 상태 (Suspended State)
- 정의: 프로세스가 메모리에서 완전히 제거되고 디스크에 저장된 상태.
- 특징:
- 시스템 자원이 부족하거나 우선순위가 낮은 프로세스를 일시 중단하여 메모리를 확보합니다.
- 사용자가 명시적으로 일시 중단할 수도 있습니다.
- 재개되면 대기 상태로 돌아갑니다.
- 예시:
- 메모리 부족으로 백그라운드 작업이 일시 중단된 경우.
6. 종료 상태 (Terminated State)
- 정의: 프로세스의 실행이 완료되어 더 이상 실행되지 않는 상태.
- 특징:
- 프로세스가 정상적으로 종료되거나 에러로 인해 종료됩니다.
- 종료된 프로세스의 정보는 부모 프로세스가 확인할 때까지 "좀비 상태(Zombie State)"로 남을 수 있습니다.
- 예시:
- 프로그램 실행이 성공적으로 끝난 경우 또는 예외 처리 없이 비정상 종료된 경우.
3.3.3 프로세스의 메모리 구조

1. 스택 (Stack)
- 용도: 함수 호출과 관련된 지역 변수, 함수의 반환 주소 등을 저장합니다.
- 특징: 메모리는 LIFO(Last In, First Out) 방식으로 할당되며, 함수 호출 시 스택 프레임이 쌓이고 함수 반환 시 제거됩니다.
- 크기: 일반적으로 제한이 있으며, 너무 많은 데이터를 스택에 저장하려 하면 스택 오버플로우가 발생할 수 있습니다.
2. 힙 (Heap)
- 용도: 동적으로 할당된 메모리 공간을 저장합니다. malloc, free, new, delete와 같은 함수나 연산자가 사용됩니다.
- 특징: 메모리는 동적으로 할당되고 해제되며, 크기에 제한이 없습니다(시스템 자원에 따라).
- 주의점: 힙 메모리는 자동으로 해제되지 않으므로 프로그래머가 명시적으로 해제해야 합니다. 그렇지 않으면 메모리 누수가 발생할 수 있습니다.
3. 데이터 영역 (Data Segment)
- 용도: 초기화된 전역 변수와 정적 변수가 저장됩니다.
- 특징: 프로그램이 시작될 때 운영체제에 의해 초기화되며, 실행 중에 값이 변경될 수 있습니다.
- 초기화된 데이터 영역: 프로그램 실행 시 이미 값이 설정된 전역 변수나 정적 변수가 여기에 저장됩니다.
- 초기화되지 않은 데이터 영역 (BSS): 값이 명시적으로 초기화되지 않은 전역 변수나 정적 변수가 여기에 저장됩니다.
4. 코드 영역 (Text Segment)
- 용도: 실행할 프로그램 코드가 저장됩니다.
- 특징: 프로그램의 명령어들이 위치하며, 읽기 전용입니다. 수정할 수 없으며, 일부 운영체제에서는 코드 영역을 보호하여 실행 중에 수정되지 않도록 합니다.
5. const 영역
- 용도: 프로그램에서 사용되는 상수 데이터가 저장됩니다.
- 특징: 읽기 전용으로, 프로그램이 실행되는 동안 변경되지 않습니다. 예를 들어, 문자열 리터럴이나 const로 선언된 변수가 이 영역에 저장됩니다.
6. rodata (Read-Only Data)
- 용도: 읽기 전용 데이터를 저장하는 영역
- 특징: 문자열 상수, 숫자 상수 등이 저장됩니다. 이 영역의 데이터는 변경할 수 없음
7. BSS (Block Started by Symbol) 영역
- 용도: 초기화되지 않은 전역 변수 및 정적 변수가 저장됩니다.
- 특징: 프로그램 시작 시 값이 0으로 초기화되며, 크기만 할당되고 실제 값은 프로그램 실행 중에 저장.
예를 들어, int globalVar;와 같이 초기값을 지정하지 않은 변수들이 이 영역에 위치
3.3.4 PCB (Process Control Block)
1. PCB
- PCB는 운영체제가 각 프로세스의 상태를 추적, 관리하는 데이터 구조.
- 각 프로세스에 대해 하나의 PCB가 존재, 프로세스 실행에 필요한 중요한 정보를 저장.
PCB의 구조
- 프로세스 상태(Process State): 프로세스의 현재 상태. 예를 들어, 준비(Ready), 실행 중(Running), 대기(Waiting), 종료(Terminated) 등이 존재.
- 프로세스 ID (PID, Process Identifier): 각 프로세스를 고유하게 식별하는 번호.
- 프로그램 카운터 (PC, Program Counter): 프로세스가 마지막으로 실행했던 명령어의 주소를 저장. 이는 컨텍스트 스위칭 시 프로세스가 재개될 위치를 추적하는 데 필요.
- 레지스터 상태(Register State): CPU의 레지스터들 (예: 범용 레지스터, 플래그 레지스터 등)의 값들을 저장. 이는 프로세스가 실행되는 동안 상태를 추적하고, 컨텍스트 스위칭 시 원래 상태로 복원하는 데 사용.
- 메모리 관리 정보(Memory Management Information): 프로세스가 사용하는 메모리 영역에 대한 정보, 예를 들어 페이지 테이블, 세그먼트 테이블 등이 포함.
- 입출력 정보(I/O Information): 프로세스가 사용 중인 입출력 장치 및 파일에 대한 정보.
- 우선순위(Priority): 프로세스 스케줄링을 위한 우선순위 값. 높은 우선순위의 프로세스가 먼저 실행될 수 있도록 함.
- 프로세스의 소유자(Owner): 프로세스를 생성한 사용자나 프로세스를 소유하는 주체에 대한 정보.
2. 컨텍스트 스위칭 (Context Switching)
- 컨텍스트 스위칭은 운영체제가 CPU를 하나의 프로세스에서 다른 프로세스로 전환하는 과정.
- 프로세스가 CPU에서 실행 중일 때, 프로세스의 상태(레지스터 값, 프로그램 카운터 등)는 PCB에 저장.
- 다른 프로세스를 실행하기 위해 CPU의 상태를 다른 프로세스의 PCB에서 복원.
컨텍스트 스위칭 과정:
- 현재 실행 중인 프로세스의 상태 저장: 실행 중인 프로세스의 레지스터 값, 프로그램 카운터 등을 PCB에 저장.
- 새 프로세스의 PCB에서 상태 복원: CPU는 새로 실행될 프로세스의 PCB에서 레지스터 값을 가져오고 프로그램 카운터를 설정.
- 새 프로세스 실행: 새 프로세스가 CPU를 할당받아 실행을 시작.
컨텍스트 스위칭은 시스템 자원을 효율적으로 관리하는 데 필수적이지만, 과도한 발생은 성능 저하를 초래할 수 있음.
3. 캐시 미스 (Cache Miss)
캐시 미스는 CPU 캐시에서 데이터를 찾을 수 없을 때 발생. 캐시는 데이터를 빠르게 접근할 수 있도록 메인 메모리보다 더 빠른 접근 시간을 제공하는 저장소. 프로세스가 실행되는 동안 자주 참조되는 데이터는 CPU 캐시로 로드.
캐시 미스의 종류:
- 컴플리트 캐시 미스(Compulsory Miss): 데이터가 처음으로 참조될 때 발생하는 캐시 미스.
- 컨플릭트 미스(Conflict Miss): 데이터가 캐시의 특정 위치에 저장되지 않아 다른 데이터와 충돌이 발생하는 미스.
- 디지털 캐시 미스(Capacity Miss): 캐시의 용량이 부족하여 데이터를 저장할 수 없을 때 발생하는 미스.
컨텍스트 스위칭이 발생하면, 다른 프로세스가 실행되므로 캐시를 비워야 할 수도 있음. 이때, 캐시 미스가 빈번하게 발생할 수 있음. 이는 성능 저하를 초래할 수 있음.
4. 스레드에서의 컨텍스트 스위칭
스레드는 프로세스 내에서 실행되는 경량화된 단위. 스레드는 동일한 프로세스 내에서 메모리 공간을 공유하지만, 독립적으로 실행될 수 있음. 스레드 간의 컨텍스트 스위칭은 프로세스 간의 컨텍스트 스위칭보다 빠를 수 있음. 이는 스레드가 메모리 공간을 공유하므로, 스레드 간 전환 시 프로세스의 주소 공간을 변경할 필요가 없기 때문.
스레드 컨텍스트 스위칭 과정:
- 현재 스레드의 상태 저장: 현재 실행 중인 스레드의 레지스터 값, 프로그램 카운터 등을 PCB나 TCB(Thread Control Block)에 저장.
- 새 스레드의 상태 복원: 실행할 스레드의 레지스터 값과 프로그램 카운터를 TCB에서 가져옴.
- 새 스레드 실행: 새로운 스레드가 실행됨.
스레드 간의 컨텍스트 스위칭은 프로세스 간의 전환보다 상대적으로 가볍고 빠를 수 있지만, 많은 스레드가 존재하면 성능에 영향을 줄 수 있음.
3.3.5 멀티프로세싱
1. 멀티 프로세싱 (Multiprocessing)
멀티 프로세싱은 여러 프로세서(CPU)를 사용하여 동시에 여러 프로세스를 처리하는 시스템 구조. 이를 통해 성능 향상 및 병렬 처리가 가능함.
2. IPC (Inter-Process Communication)
IPC는 서로 다른 프로세스 간에 데이터를 교환하거나 정보를 공유하는 방법. 멀티 프로세싱 환경에서 프로세스 간 통신을 가능하게 함.
3. IPC 방식
IPC 방식 | 특징 | 통신 방향 | 예시 |
파일 | 파일을 통해 데이터를 저장하고 읽는 방식. | 양방향 | 데이터베이스, 로그 파일 공유 |
소켓 | 네트워크를 통해 데이터를 주고받는 방식. | 양방향 | 클라이언트-서버 모델, 분산 시스템 |
익명 파이프 | 부모-자식 프로세스 간에 데이터를 일방향으로 전달하는 방식. | 단방향 | 부모-자식 프로세스 간 통신 |
명명된 파이프 | 여러 프로세스 간 양방향 통신이 가능한 파이프. | 양방향 | 서버-클라이언트 간 데이터 전송 |
메시지 큐 | 메시지를 큐에 넣고, 큐에서 메시지를 꺼내 처리하는 방식. | 비동기적, 양방향 | 프로세스 간 비동기 메시지 전송 |
4. IPC 방식의 특징
- 파일: 데이터 저장 및 읽기를 통한 통신. 동기화 필요.
- 소켓: 네트워크를 통한 양방향 통신. 분산 시스템에 적합.
- 익명 파이프: 부모-자식 간 일방향 통신. 빠르고 간단.
- 명명된 파이프: 여러 프로세스 간 양방향 통신. 파일 시스템에서 접근.
- 메시지 큐: 비동기적 메시지 전송. 큐에 메시지를 넣고, 다른 프로세스가 이를 처리.
3.3.6 스레드와 멀티스레딩
1. 쓰레드 (Thread)
쓰레드는 프로세스 내에서 실행되는 경량화된 실행 단위. 쓰레드는 프로세스 내에서 메모리 자원을 공유하며, 독립적으로 실행되는 작업. 하나의 프로세스는 여러 개의 쓰레드를 가질 수 있음. 이를 멀티쓰레딩(Multithreading)이라고 함.
쓰레드의 특징:
- 경량성: 쓰레드는 프로세스 내에서 실행되므로 별도의 메모리 공간을 할당받지 않으며, 프로세스의 자원(메모리, 파일 등)을 공유. 따라서, 쓰레드 간 생성과 전환은 프로세스보다 훨씬 가볍고 빠름.
- 공유 자원: 동일한 프로세스 내의 쓰레드들은 메모리, 파일 핸들, 데이터 등 대부분의 자원을 공유. 쓰레드 간 통신은 빠르고 효율적.
- 독립성: 쓰레드는 독립적으로 실행되지만, 프로세스 내 다른 쓰레드와 협력하여 작업을 수행할 수 있음. 각 쓰레드는 실행 흐름을 가지며, 하나의 프로세스 내에서 다수의 작업을 동시에 처리할 수 있음.
쓰레드의 종류:
- 사용자 수준 쓰레드(User-Level Thread): 사용자 프로그램에서 직접 관리되는 쓰레드. 운영체제는 이 쓰레드를 인식하지 못하고, 사용자가 스케줄링 및 관리.
- 커널 수준 쓰레드(Kernel-Level Thread): 운영체제의 커널이 관리하는 쓰레드. 이 쓰레드는 운영체제가 스케줄링하고 관리하여, 다수의 프로세스가 동시에 실행될 수 있음.
쓰레드 간 통신:
- 쓰레드는 동일한 프로세스 내에서 실행되므로, 프로세스의 자원을 공유. 이를 통해 쓰레드 간 통신(쓰레드 간 데이터 공유)을 효율적으로 할 수 있음.
- 여러 쓰레드가 같은 자원을 공유할 때, 동기화(Synchronization) 문제를 해결해야 함. 이를 위해 뮤텍스(Mutex), 세마포어(Semaphore) 등의 기법이 사용됨.
2. 멀티태스킹 (Multitasking)
멀티태스킹은 하나의 CPU에서 여러 작업을 동시에 처리하는 기법. CPU는 여러 프로세스를 빠르게 전환하면서 동시에 여러 작업을 수행하는 것처럼 보임.
멀티태스킹의 종류:
- 선점형 멀티태스킹(Preemptive Multitasking): 운영체제가 프로세스를 일정 시간 간격으로 강제로 전환. 각 프로세스는 일정 시간 동안 CPU를 사용하고, 그 후 운영체제가 다른 프로세스로 전환.
- 비선점형 멀티태스킹(Cooperative Multitasking): 프로세스가 자발적으로 CPU를 다른 프로세스에게 넘겨주는 방식. 하나의 프로세스가 CPU를 사용하고 있을 때, 다른 프로세스는 실행되지 않음.
멀티태스킹을 통해 여러 작업을 동시에 실행하는 것처럼 보이지만, 실제로는 CPU가 프로세스 간에 전환되며, 컨텍스트 스위칭(Context Switching)이 발생함. 이는 시스템 자원을 효율적으로 활용하는 데 중요한 기법.
멀티태스킹의 장점:
- CPU 자원 활용 최적화: 여러 작업을 동시에 처리할 수 있으므로, CPU 자원의 활용도가 높아짐.
- 응답성 향상: 사용자 작업이나 입출력 작업을 다른 프로세스가 차지하지 않도록 하여 시스템 응답성이 향상됨.
멀티태스킹의 단점:
- 컨텍스트 스위칭 오버헤드: 프로세스 간 전환이 자주 일어나면 시스템 성능에 영향을 줄 수 있음.
- 자원 충돌: 여러 프로세스가 동시에 자원을 요청할 경우 충돌이 발생할 수 있음
3.3.7 공유 자원과 임계 영역
1. 공유 자원 (Shared Resource)
공유 자원은 여러 프로세스나 스레드가 동시에 접근할 수 있는 자원. 예: 메모리, 파일, 데이터베이스, 입출력 장치 등. 여러 프로세스나 스레드가 동시에 공유 자원에 접근할 경우 동기화(Synchronization)가 필요.
2. 임계영역 (Critical Section)
임계영역은 공유 자원에 접근하는 코드 부분. 여러 프로세스나 스레드가 동시에 접근하면 데이터 무결성이 깨질 수 있음. 임계영역에 대한 접근을 상호 배제(Mutual Exclusion) 기법으로 제어.
임계영역의 문제:
- 상호 배제: 한 번에 하나의 프로세스나 스레드만 임계영역에 접근할 수 있음.
- 진입 허용: 다른 프로세스가 자원을 사용 중일 경우 대기해야 함.
- 진행: 한 프로세스가 무기한 대기하지 않도록 해야 함.
- 한정적 대기: 무한 대기를 방지해야 함.
3. 뮤텍스 (Mutex)
뮤텍스는 상호 배제를 제공하는 동기화 객체. 하나의 프로세스나 스레드만 임계영역에 접근할 수 있도록 보장.
뮤텍스의 동작:
- 획득 (Lock): 프로세스가 자원을 사용할 수 있을 때까지 대기.
- 해제 (Unlock): 프로세스가 자원 사용을 마친 후, 다른 프로세스가 자원을 사용하도록 해제.
4. 세마포어 (Semaphore)
세마포어는 공유 자원의 접근을 제어하는 동기화 기법. 세마포어는 카운터 값을 이용해 접근을 제어.
세마포어의 종류:
- 바이너리 세마포어 (Binary Semaphore): 값이 0과 1만 가질 수 있는 세마포어. 뮤텍스와 유사하게 상호 배제를 제공.
- 카운팅 세마포어 (Counting Semaphore): 세마포어 값이 0 이상의 정수 값을 가질 수 있으며, 자원의 개수에 따라 접근을 제어.
5. 모니터 (Monitor)
모니터는 공유 자원에 대한 접근을 관리하는 고급 동기화 기법. 모니터는 데이터와 해당 데이터를 처리하는 절차를 하나의 단위로 묶어 관리.
모니터의 특징:
- 내부 동기화: 모니터 내의 모든 절차는 상호 배제 상태에서 실행됨.
- 조건 변수 (Condition Variable): 대기 상태에서 프로세스나 스레드를 깨우거나 기다리게 하는 데 사용됨.
모니터는 프로그래밍 언어에서 제공하는 동기화 기법으로, 상호 배제와 동기화를 쉽게 구현할 수 있도록 돕는 객체.3.3.8 교착 상태
1. 교착상태 (Deadlock)
교착상태는 둘 이상의 프로세스가 서로 자원을 기다리며, 아무도 자원을 획득하지 못하고 영원히 대기하는 상태. 교착상태에 빠진 프로세스들은 더 이상 진행되지 않으며, 시스템의 자원은 효율적으로 사용되지 않음.
2. 교착상태의 원인
교착상태가 발생하는 데에는 네 가지 조건이 동시에 충족되어야 함. 이 네 가지 조건은 교착상태의 필요 조건으로 알려져 있음.
교착상태의 네 가지 필요 조건:
- 상호 배제 (Mutual Exclusion): 자원은 한 번에 하나의 프로세스만 사용할 수 있음.
- 점유 및 대기 (Hold and Wait): 최소한 하나의 자원을 점유하고 있는 프로세스가 다른 자원을 기다리는 상태.
- 비선점 (No Preemption): 자원을 점유하고 있는 프로세스가 자원을 강제로 빼앗길 수 없음.
- 원형 대기 (Circular Wait): 프로세스들이 원형으로 서로 자원을 기다리는 상태. 예를 들어, 프로세스 A는 자원 1을 기다리고, 프로세스 B는 자원 2를 기다리며, 프로세스 C는 자원 3을 기다리고, 다시 프로세스 A가 자원 1을 기다리는 식으로 순환.
3. 교착상태의 해결 방안
교착상태를 해결하거나 방지하기 위해 여러 가지 방법을 사용할 수 있음.
1) 교착상태 예방 (Deadlock Prevention)
교착상태가 발생하지 않도록 시스템의 자원 할당 방식을 제어하는 방법.
- 상호 배제 방지: 일부 자원에 대해 상호 배제를 없애는 방법. 예를 들어, 다수의 프로세스가 동시에 읽을 수 있는 자원은 상호 배제를 적용하지 않음.
- 점유 및 대기 방지: 프로세스가 자원을 요청할 때, 다른 자원을 보유하고 있지 않도록 요구. 또는, 프로세스가 자원을 요청할 때 모든 자원을 한번에 요청하도록 강제.
- 비선점 방지: 자원을 강제로 회수할 수 있는 방식으로 시스템을 설계. 자원을 점유한 프로세스가 자원 요청을 할 때, 이미 점유한 자원을 해제해야만 새 자원을 요청하도록 함.
- 원형 대기 방지: 자원을 요청하는 순서에 제약을 두어, 프로세스가 자원을 요청하는 순서에 따라 교착상태를 예방.
2) 교착상태 회피 (Deadlock Avoidance)
교착상태를 발생할 가능성이 있는 상태를 미리 회피하는 방법. 시스템이 자원을 할당할 때, 자원이 할당된 후에도 교착상태가 발생하지 않도록 주의.
- 안전 상태(Safe State)와 위험 상태(Unsafe State): 시스템은 자원을 할당하기 전에 현재 상태가 안전 상태인지 확인. 안전 상태에서는 프로세스들이 자원을 할당받고 종료될 수 있음.
- 은행가 알고리즘 (Banker's Algorithm): 프로세스가 자원을 요청할 때, 이 요청이 시스템의 안전 상태를 유지할 수 있는지 검사. 안전 상태라면 자원을 할당하고, 그렇지 않으면 요청을 거부.
3) 교착상태 탐지 및 복구 (Deadlock Detection and Recovery)
교착상태가 발생했다고 가정하고 이를 탐지한 후, 교착상태를 복구하는 방법.
- 교착상태 탐지: 교착상태를 탐지하기 위한 알고리즘을 사용. 예를 들어, **자원 할당 그래프(Resource Allocation Graph)**나 **기다림 그래프(Wait-for Graph)**를 사용하여 교착상태를 탐지.
- 교착상태 복구: 교착상태를 해결하기 위해 한 프로세스를 종료하거나, 프로세스가 점유한 자원을 강제로 회수하는 방법을 사용.
- 프로세스 종료: 교착상태에 포함된 프로세스를 종료하여 자원을 해제.
- 자원 회수: 일부 프로세스가 점유한 자원을 강제로 회수하여 다른 프로세스에 할당.
4) 교착상태 회복을 위한 프로세스 관리 기법
- 프로세스 종료: 교착상태에 참여한 프로세스를 하나씩 종료하여, 자원을 회수하고 교착상태를 해결.
자원 회수: 프로세스가 자원을 점유한 상태에서 강제로 자원을 회수하여 교착상태를 해소. 자원을 회수한 프로세스는 다시 실행될 수 있음.
'SW개발 > 면접을 위한 CS 전공지식 노트' 카테고리의 다른 글
참고. 가상 메모리, 페이징 기법, Segmentation Fault (0) | 2025.01.17 |
---|---|
3.4 CPU 스케줄링 알고리즘 (1) | 2025.01.15 |
3.2 메모리 (0) | 2025.01.15 |
3.1 운영체제와 컴퓨터 (1) | 2025.01.15 |
참고. 네트워크 기기 (1) | 2025.01.10 |