floatFirstTOC: right
🖥️ 시작하며💡 각 용어의 차이1️⃣ 프로그램 (Program)2️⃣ 프로세스 (Process)3️⃣ 프로세서 (Processor)4️⃣ 태스크 / 작업 (Task / Job)🔍 프로세스란?🔍 프로세스의 발생📌 프로세스 특성1️⃣ Resource sharing2️⃣ Execution3️⃣ Address space📌 프로세스의 종료🔍 fork()🔍 Zombie VS Orphan📌 Zombie Process (Defunct Process)📌 Orphan Process🔍 프로세스 상태 변화📌 프로세스 데이터 구조 (PCB, Process Control Block)🔍 Context Switch 📌 Process State Queue📌 PCB와 상태 큐💡 fork() 실행 과정📌 exec()
🖥️ 시작하며
프로세스에 대한 정확한 정의와 프로세스 구현에 대한 방법을 알아봅니다.
💡 각 용어의 차이
1️⃣ 프로그램 (Program)
- 정의: 명령어들의 나열된 순서
- 설명: 프로그램은 실행 가능한 파일로, 코드와 데이터의 집합입니다.
2️⃣ 프로세스 (Process)
- 정의: 특정 목적을 수행하기 위해 실행되는 과정
- 설명: 프로세스는 실행 중인 프로그램으로, 운영 체제에서 자원을 할당받아 실행됩니다.
3️⃣ 프로세서 (Processor)
- 정의: 하드웨어, 프로그램 실행 장치
- 설명: 프로세서는 CPU(Central Processing Unit)를 의미하며, 프로그램의 명령어를 실제로 실행하는 하드웨어입니다.
4️⃣ 태스크 / 작업 (Task / Job)
- 정의: 프로세스의 묶음
- 설명: 태스크 또는 작업은 다수의 프로세스를 포함하는 더 큰 작업 단위입니다.
🔍 프로세스란?
프로그램 실행의 인스턴스
- 프로세스는 프로그램 내 제어 흐름을 캡슐화합니다.
- 프로세스는 동적이고 활동적인 엔티티입니다.
- 프로세스는 실행 및 스케줄링의 기본 단위입니다. (추후 스레드가 기본 단위가 됩니다.)
- 프로세스는 고유한 PID로 식별됩니다.
- 프로세스 구성 요소:
- CPU 컨텍스트: 레지스터 상태를 포함합니다.
- 운영 체제 자원: 메모리, 열린 파일 등을 포함합니다.
- 기타 정보: PID, 상태, 소유자 등을 포함합니다.
🔍 프로세스의 발생
모든 프로세스는 계층 구조를 가짐, 한 프로세스가 다른 프로세스 생성
- 프로세스는 시스템 콜을 통해 자식 프로세스를 생성한다!
fork()
,CreateProcess()
- 시스템이 초기화될 때, 이를
init process
라 말하며PID 1
을 가진다.
📌 프로세스 특성
1️⃣ Resource sharing
- 부모 프로세스가 자원과 권한을 자식에게 상속
2️⃣ Execution
- 부모 프로세스는 자식 프로세스가 끝날 때까지 기다리거나 병렬로 계속 실행
3️⃣ Address space
- 자식 프로세스는 부모의 주소 공간을 복제하거나 새로운 프로그램을 로드:
→ 같은 주소 공간을 공유하지 않는 이유는 독립성, 안정성 확보하기 위함입니다.
📌 프로세스의 종료
유형 | 설명 | 예시 | 자발성 |
정상 종료 (Normal Exit) | 프로그램이 예상대로 종료됨 | 프로그램 종료, 종료 버튼 클릭 | 자발적 |
오류 종료 (Error Exit) | 프로그램이 오류를 감지하고 종료됨 | 파일 없음 오류, 네트워크 오류 | 자발적 |
치명적 오류 (Fatal Error) | 예기치 않은 오류로 인해 프로그램이 강제로 종료됨 | Segmentation Fault, Protection Fault | 비자발적 |
다른 프로세스에 의해 종료 | 외부 요인에 의해 프로그램이 종료됨 | kill 명령어, 시스템 관리자에 의한 종료 | 비자발적 |
🔍 fork()
자식 프로세스를 만드는 시스템 콜
- 부모 프로세스의 가상 주소 공간을 전체 복사하여 자식 프로세스를 만듭니다.
- 자식 프로세스를 관리하기 위한 내부 데이터 구조를 복사합니다.
- PCB를 전체 복사하는 것과 같습니다.
- 부모 프로세스는 자식 프로세스의 PID를 받습니다.
- 자식 프로세스는 0 값을 받습니다.
→ 주의! 무조건 0이나 자식의 PID를 반환하는 것은 아닙니다. 오류로 -1을 반환할 수도 있습니다.
🔍 Zombie VS Orphan
📌 Zombie Process (Defunct Process)
실행을 완료한 프로세스가 여전히 Process Table 엔트리에 남아 있는 경우
→ 자식 프로세스에서 발생하며, 부모 프로세스가 자식의 종료 상태를 알 수 있도록 필요하기 때문에 발생합니다.
📌 Orphan Process
부모가 먼저 죽어 고아가 된 프로세스
→ 부모 프로세스에서 발생하며, 고아가 된 자식 프로세스가 init 프로세스에 입양됩니다.
🔍 프로세스 상태 변화
📌 프로세스 데이터 구조 (PCB, Process Control Block)
프로세스의 메타데이터를 포함하는 데이터 구조
- PCB에는 프로세스에 대한 모든 정보가 포함되어 있습니다:
- 프로세스 상태
- 프로그램 카운터
- CPU 레지스터
- CPU 스케줄링 정보
- 메모리 관리 정보
- 회계 정보
- 입출력 상태 정보 등
- Linux에서의
task_struct
: - Linux 2.4.18 기준으로 1456 바이트
include/linux/sched.h
에 정의됨
- 프로세스가 실행 중일 때:
- 하드웨어 상태는 CPU 내부에 존재:
- 프로그램 카운터(PC)
- 스택 포인터(SP)
- 레지스터
- 운영체제(OS)가 프로세스 실행을 중지할 때:
- 레지스터의 값을 프로세스 제어 블록(PCB)에 저장한다.
- 운영체제가 프로세스를 실행 상태로 만들 때:
- 하드웨어 레지스터를 해당 프로세스의 PCB에 있는 값으로 로드한다.
🔍 Context Switch
CPU를 한 프로세스에서 다른 프로세스로 전환하는 행위 → 오버헤드가 발생!
- 캐시 메모리에 있던 값을 날렸다가 다시 hit하면서 올라와야 하기 때문에 오버헤드가 발생합니다.
- 이는 하드웨어가 도와주면 비교적 쉽게 작동합니다.
- 레지스터를 여러 개 만든다던지 등
- 초당 100 ~ 1000번의 context switch가 일어납니다.
📌 Process State Queue
운영체제가 프로세스를 관리하는 큐
- 준비 큐(Ready queue)
- 대기 큐(Wait queue): 각 유형의 대기(장치, 타이머, 메시지 등)에 대해 여러 개의 대기 큐가 있을 수 있다.
- 각 프로세스 제어 블록(PCB)은 현재 상태에 따라 상태 큐에 대기된다.
- 프로세스의 상태가 변경됨에 따라 PCB는 다양한 큐 사이를 이동한다.
📌 PCB와 상태 큐
- PCB(프로세스 제어 블록)는 데이터 구조입니다.
- OS 메모리 내에서 동적으로 할당됩니다.
- 프로세스가 생성될 때:
- OS는 프로세스를 위해 PCB를 할당합니다.
- OS는 PCB를 초기화합니다.
- OS는 PCB를 올바른 큐에 넣습니다.
- 프로세스가 계산을 수행할 때:
- OS는 PCB를 큐에서 큐로 이동시킵니다.
- 프로세스가 종료될 때:
- OS는 PCB를 할당 해제합니다.
💡 fork() 실행 과정
- PCB 생성, 초기화
- child 공간 생성, 초기화
- 부모 내용 복제
- 커널 자원 세팅, 초기화
- PCB ready queue에 삽입
- 부모에게 Child PID, Child 0 반환
📌 exec()
- 현재 프로세스를 정지시킵니다.
- 프로그램 "prog"를 프로세스의 주소 공간에 로드합니다.
- 새로운 프로그램을 위해 하드웨어 컨텍스트와 인수를 초기화합니다.
- PCB를 준비 큐에 넣습니다.
- 주의:
exec()
는 새로운 프로세스를 생성하는 것이 아닌, 덮어씌우는 것입니다.
부모 프로세스와 자식 프로세스 모두 별도 프로세스이므로, 각자의 값을 볼 수 없음
댓글