프로세스(Process) 프로그램을 구동하여 메모리 상에서 실행되는 작업(task)의 단위로, 프로그램이 메모리에 로드되어 실행중인 상태를 의미한다. '작업(task)'이라는 용어와 동일한 의미로 사용된다. (프로그램(Program) : 하드디스크에 저장되어 있는 코드로, 컴퓨터에서 실행되기 전의 저장된 코드를 의미)
프로세스 주소 공간(thread address space): 프로세스가 실행되면 코드(Text), 데이터(Data), 스택(Stack), 힙(Heap) 영역 등이 메모리에 할당된다.
프로세스 영역
코드(Text) 영역 : 실행할 프로그램의 코드가 저장되는 영역으로, 함수, 제어문, 상수 등이 저장됨
데이터(Data) 영역 : 전역 변수와 정적 변수(static)가 할당되는 부분으로, 프로그램 종료 시 메모리에서 소멸된다는 특징이 있음.
스택(Stack) 영역 : 프로그램이 자동으로 사용하는 임시 메모리 영역으로, 지역 변수와 함수의 매개변수가 저장됨 (함수 호출이 완료되면 해당 정보는 사라짐)
힙(Heap) 영역 : 프로그래머가 할당 및 해제하는 메모리 공간으로, 동적 할당되는 영역
프로세스는 시스템의 자원을 할당받고 작업을 수행하므로, 프로세스 관리는 운영 체제의 중요한 부분임
스레드(Thread) 프로세스 내에서 더 세분화된 실행 단위로, 프로세스의 메모리 공간을 공유하면서 독립적으로 실행되는 작업 단위를 의미한다.
스레드 사용의 이점👍🏻
사용자 응답성의 증가 프로세스를 여러 스레드로 분할하면 일부 스레드가 지연되더라도 다른 스레드가 계속 작동하여 애플리케이션의 응답을 유지할 수 있다.
다중 처리로 성능 향상 및 효율적인 자원 활용 스레드를 활용하면 컬티 코어 프로세서에서 작업을 병렬로 실행할 수 있어 서로 다른 CPU 코어에서 여러 스레드가 동시에 처리되므로 성능 향상이 가능하다. 또한 멀티 스레드를 활용하면 여러 프로세스를 사용하는 것보다 추가 리소스 할당 및 문맥 교환(Context Switch) 비용이 감소한다.
통신의 용이성 프로세스 간 통신에는 특별한 기술(IPC, Inter-Process Communication)이 필요하지만, 스레드는 동일한 메모리 공간을 공유하므로 데이터 교환이 용이하다.
스레드 사용의 단점👎🏻
불안정성 및 취약성 스레드는 동일한 메모리 공간을 공유하므로, 한 스레드가 실수로 다른 스레드에서 사용하는 메모리를 덮어쓸 수 있으며, 이로 인해 예측 불가능한 동작 및 충돌, 또는 보안의 취약성이 발생할 수 있다.
동기화의 복잡성 여러 스레드를 관리하려면 개발 및 디버깅 프로세스를 복잡하게 할 수 있는 경쟁 상태(race condition), 교착 상태(deadlock) 등의 문제를 피하기 위해 신중한 동기화가 필요하다.
⚠️ 스레드(Thread)의 분류
1️⃣ 사용자 수준의 스레드(User-Level Thread) 사용자 스레드는 커널(Kernel) 영역의 상위에서 지원되며, 일반적으로 사용자 정의 라이브러리를 통해 구현된다. 이 경우, 커널은 스레드의 존재를 인식하지 못하므로 커널의 개입 없이 사용자 정의 라이브러리를 사용해 스레드를 관리하게 된다.
- 다수의 사용자 수준 스레드가 커널 수준 스레드 1개에 매핑되므로, 다대일(n:1) 스레드 매핑 이라고 한다. 출처: https://dev-yyh.github.io/OS/4 - 사용자 영역에서 생성 및 관리되므로 속도가 빠르며, 이식성(portability)이 높아 모든 운영체제에서 실행이 가능하다는 장점을 가진다.
- 그러나 커널(Kernel)에서 스레드가 하나라고 판단하기 때문에, 하나의 스레드가 중단되면 나머지 모든 스레드 역시 중단된다는 단점이 있다. (사용자 수준의 스레드들은 여러 개가 존재하더라도 커널에서 인식하기론 하나로 인식하므로)
- 또한 구현 속도가 빠르다는 장점과, 구현 자체가 어렵다는 단점을 동시에 가진다.
2️⃣ 커널 수준의 스레드(Kernel-Level Thread) 커널 수준의 스레드는 운영체제(OS, Operating System)가 지원하는 스레드 기능으로 구현되며, 커널이 스레드의 생성 및 스케줄링 등을 관리한다.
- 사용자 수준의 스레드와 커널 수준의 스레드가 일대일(1:1) 매핑되므로, 사용자 수준 스레드를 생성하면 이에 대응하는 커널 스레드를 자동으로 생성한다. 출처: https://dev-yyh.github.io/OS/4 - 커널(Kernel)이 각 스레드를 개별적으로 관리하므로, 프로세스(Process) 내의 스레드들이 병렬적으로 수행이 가능하다. 따라서 하나의 스레드가 중단되어도 다른 스레드는 계속 수행이 가능하다는 장점을 가진다.
- 또한 구현이 상대적으로 쉽다는 장점을 가지지만, 사용자 수준의 스레드(User-Level Thread)보다 생성 및 관리 속도가 느리다는 단점을 가진다.
3️⃣ 혼합형 스레드 사용자 수준의 스레드(User-Level Thread)와 커널 수준의 스레드(Kernel-Level Thread)를 혼합한 구조이다.
- 사용자 수준 스레드는 커널 수준 스레드와 비슷한 경량 프로세스에 다대다(n:m)로 매핑되며, 경량 프로세스는 커널 수준 스레드와 일대일(1:1)로 매핑된다. 따라서 다수의 사용자 수준 스레드에 다수의 커널 수준 스레드가 다대다(n:m)로 매핑된다. 출처: https://dev-yyh.github.io/OS/4
- 프로세스 내 스레드들을 병행 수행할 수 있으며, 스레드 풀링(Thread Pooling) 기법을 통해 일대일(1:1) 스레드 매핑에서의 오버 헤드(Overhead)를 줄여준다는 장점이 있다.
- 하지만 구현 및 관리가 복잡하다는 단점이 있다.
✅ 프로세스의 상태
프로세스는 생성부터 실행 및 완료까지 위와 같은 상태 변화를 거친다.
생성(Create) 상태: 사용자에 의해 프로세스가 생성된 상태
제출(Submit): 사용자가 작업을 시스템(디스크)에 제출한 상태
접수(Hold): 제출된 작업이 디스크의 Spool 공간에 저장된 상태
준비(Ready) 상태: 프로세스가 프로세서 할당을 기다리는 상태(프로세서: 중앙 처리 장치. 즉 CPU에 해당한다.)
CPU를 할당받을 수 있는 상태
준비 리스트(Ready List / Ready Queue): 프로세스에 우선순위를 부여하여 해당 순서대로 CPU를 할당받음
실행(Running) 상태: 프로세스가 프로세서를 할당받아 동작 중인 상태
대기(Waiting) 상태: 프로세스 실행 중, I/O 처리(입출력 처리)가 필요하여 실행을 중단하고 CPU를 양도한 채 I/O 처리가 완료될 때까지 대기 리스트에서 기다리는 상태
대기 리스트(Waiting List): 우선순위가 존재하지 않음
완료(Complete) 상태: 프로세스 실행이 끝나고 할당이 해제된 상태로, 프로세스가 CPU를 할당받은 후 주어진 시간 내에 완전히 수행을 종료했음을 의미
✅ 프로세스의 상태 전이
하나의 작업(프로세스)이 컴퓨터 시스템에 입력되고 완료되기까지는 아래와 같이 여러 번의 상태 변화가 이루어진다.
Dispatch(디스패치): 준비 상태 → 실행 상태로 전이되는 과정, 스케줄링
준비 리스트(Ready List) 내의 프로세스들 중 실행될 프로세스를 선정(Scheduling)하여 CPU를 할당함(Dispatching) ▷ 이때 발생하는 것이 "문맥 교환(Context Switching)"
Timer run out (타이머 런 아웃): 실행 상태 → 준비 상태로 전이되는 과정, 선점형
CPU를 할당받은 프로세스(process)는 지정된 시간이 초과되면, 스케줄러에 의해 PCB(프로세스 제어 블럭) 저장됨 ( → 따라서 CPU를 반납하고 다시 준비 상태로 전이된다.)
타임 슬라이스(Time Slice) 만료, 선점(Preemption) 시에 타임아웃이 발생함
Block (블록): 실행 상태 → 대기 상태로 전이되는 과정, 입출력 대기 또는 사건 대기
실행 상태에 있는 프로세스가 지정된 할당 시간을 초과하기 전에, 입출력(I/O) 또는 기타 사건이 발생(block)하면 CPU를 스스로 반납하고 입출력이 완료될 때까지 대기 상태로 전이됨
시스템 콜, I/O 작업의 시작, 프로세스 간 통신 시에 블록이 발생함
Wake Up (웨이크 업): 대기 상태 → 준비 상태로 전이되는 과정, 입출력 또는 이벤트의 완료
입출력(I/O)이 종료되는 순간에 대기 상태의 프로세스에게 입출력 종료 사실을 wait & signal 등으로 알려주고, 상태 전이함
Spooling: 입/출력 데이터를 모아뒀다가 한꺼번에 입/출력하기 위해 디스크에 저장하는 과정
Swap-in (재시작): 프로세스에게 다시 기억장치가 할당되는 것을 의미
지연 준비 상태 or 지연 대기 상태 → 준비 상태 or 대기 상태
Swap-out (중단): 프로세스가 기억장치를 잃는 것을 의미
준비 상태 or 대기 상태 → 지연 준비 상태 or 지연 대기 상태
💡문맥 교환 (Context Switching)
CPU가 현재 실행하고 있는 프로세스(process)의 문맥 상태를 프로세스 제어 블럭(PCB)에 저장하고, 다음 프로세스의 PCB로부터 문맥을 복원하는 작업을 의미함
컴퓨터 시스템에서 중앙처리장치(CPU)와 입출력 장치가 독립적으로 동작하도록 함으로써 시스템에서 중앙처리장치에 비해 주변 장치의 처리 속도가 느려서 발생하는 대기시간을 줄이기 위해 고안된 기법
- Spool 공간 Spooler (스풀러, 대기열 관리 프로그램) 또는 인쇄 관리 소프트웨어라고도 하며, 우선 순위를 작업에 할당하고, 인쇄할 때 사용자에게 알리며, 프린터끼리 서로 작업을 나누는 등의 일을 담당함
- Spooling (스풀링) 스풀을 적용하는 것 또는 스풀을 위해 마련된 저장 공간을 채우는 동작을 의미함
✅ PCB(Process Control Block, 프로세스 제어 블록)
특정한 프로세스를 관리할 필요가 있는 정보를 포함하는 운영 체제 커널(Kernel)의 자료 구조로, 작업 제어 블록(Task Control Block, TCB) 또는 작업 구조라고도 한다. 운영체제가 프로세스의 정보를 저장하는 공간으로, 각 프로세스가 생성될 때마다 고유한 PCB가 생성되고 프로세스 종료 시 해당 PCB는 제거된다.
✔️ PCB는 운영 체제가 프로세스를 표현한 것이다.
PCB에 저장되는 정보는 아래와 같다.
프로세스 상태 (Process State)
프로세스 포인터 (부모 프로세스, 자식 프로세스 등)
프로세스 고유 식별자 (Process ID)
스케줄링 정보 및 프로세스 우선순위⭐
CPU 레지스터 정보
주기억장치(메모리) 관리 정보 (주기억장치: RAM)
I/O (입출력) 상태 정보
계정 정보 (예를 들어 CPU 사용 시간, 실제 사용 시간, 한정된 시간 등에 대한 정보)
✅ 문맥 교환 (Context Switching)
하나의 프로세스가 CPU 사용을 마치고 다른 프로세스가 CPU를 사용하도록 전환하는 과정을 의미하며, 이 과정에서 현재 실행중인 프로세스의 상태(문맥, Context)는 프로세스 제어 블록(PCB)에 저장되며 새로운 프로세스의 상태는 PCB에서 읽어 CPU 레지스터에 적재된다.
문맥 교환(Context Switching)은 멀티태스킹(멀티프로세싱)을 가능하게 하며, 여러 프로세스가 동시에 실행되는 것처럼 보이게 한다. (빠르게 전환하여 동시에 실행되는 것처럼 보이게 한다는 의미. 즉 병행을 의미함)