
프로세스
실행중인 프로그램

- 보조기억장치에 저장된 프로그램을 실행해서 메모리에 적재하고 실행되는 순간에 프로그램은 프로세스가 됨

- 프로세스는 작업관리자에서도 쉽게 확인할 수 있음
PS 명령어
- 리눅스, macOS
- 프로세를 확인하는 명령어

프로세스의 종류
포그라운드 프로세스(foreground process)
- 사용자가 볼 수 있는 공간에서 실행되는 프로세스
백그라운드 프로세스(background process)
- 사용자가 볼 수 없는 공간에서 실행되는 프로세스
- 2가지 종류로 나뉨
- 사용자와 직접 상호작용이 가능한 백그라운 프로세스
- 사용자와 상호작용하지 않고 그저 정해진 일만 수행하는 프로세스
= 데몬(daemon) or 서비스(service)

프로세스 제어 블록(PCB)
- 모든 프로세스는 자원 실행을 위해 CPU가 필요하지만, CPU자원은 한정되어 있다
- 그래서 프로세스들은 돌아가며 한정된 시간 만큼만 CPU를 이용한다
- 자신의 차례에 정해진 시간 만큼 CPU 이용
- 타이머 인터럽트가 발생하면 차례 양보

- 빠르게 번갈아 수행되는 프로세스들을 관리해야 하는데,
이를 위해 사용하는 자료구조가 프로세스 제어 블록(PCB)
프로세스 제어 블록
- 프로세스 관련 정보를 저장하는 자료 구조
- 마치 상품에 달린 태그와 같은 정보
- 프로세스 생성 시 커널 영역에 생성, 종료 시 폐기
- PCB에 담기는 정보는 운영체제마다 차이가 있음
PCB에 담기는 대표적인 정보
- 프로세스 ID (= PID)
- 레지스터 값
- 프로세스 상태
- CPU 스케줄링 정보
- 메모리 정보
- 사용한 파일과 입출력장치 정보


PCB에 담기는 정보 자세히 보기
- 프로세스 ID (= PID)
- 특정 프로세스를 식별하기 위해 부여하는 고유한 번호(학교의 사번, 회사의 사번)

작업관리자 - 상태 위 우클릭 - PID
- 특정 프로세스를 식별하기 위해 부여하는 고유한 번호(학교의 사번, 회사의 사번)
- 레지스터 값
- 프로세스는 자신의 실행 차례가 오면 이전까지 사용한 레지스터 중간 값을 모두 복원 => 실행 재개
- 프로그램 카운터, 스택 카운터.. 등의 레지스터 값을 저장
- 프로세스 상태
- 생성 / 대기 / 준비 / 실행 / 종료 상태 등(아래에서 자세히)
- CPU 스케줄링 정보
- 프로세스마다 CPU를 돌아가면서 사용하지만, 동일한 시간만큼 사용하는 것은 아님
- 그러므로 언제 어떤 순서로 CPU를 할당받아 사용할지에 대한 스케줄링 정보를 저장해 둠
- 메모리 정보
- 프로세스가 어느 주소에 저장되어 있는지에 대한 정보
- 페이지 테이블 정보(메모리 주소를 알 수 있는 정보)
- 사용한 파일과 입출력장치 정보
- 할당된 입출력장치, 사용 중인(열린) 파일 정보
문맥 교환 (context switch)
- 기존의 실행 중인 프로세스의 문맥을 백업하고
새로운 프로세스 실행을 위해 문맥을 복구하는 과정(context switching) - 여러 프로세스가 끊임없이 빠르게 번갈아가며 실행되는 원리


- 한 프로세스(A)에서 다른 프로세스(B)로 실행 순서가 바뀌는 과정
- 기존에 실행되던 프로세스 A는 지금까지 중간 정보를 백업
- 프로그램 카운터 등 각종 레지스터 값, 메모리 정보, 열었던 파일, 사용한 입출력 장치 등 다음 차례가 왔을 때 실행을 재개하기 위한 정보
- 이러한 정보를 문맥(context) 라고 함
- 실행 문맥을 백업해두면 언제든 해당 프로세스의 실행을 재개할 수 있음
- 뒤이어 실행할 프로세스 B의 문맥을 복구
- 자연스럽게 실행 중인 프로세스가 바뀜
- 기존에 실행되던 프로세스 A는 지금까지 중간 정보를 백업
프로세스의 메모리 영역
- 커널 영역에는 PCB가, 사용자 영역에는?
- 대표적으로 4가지 영역 : 코드 영역(= 텍스트 영역), 데이터 영역, 힙 영역, 스택 영역

정적 할당 영역
- 코드영역과 데이터 영역
- 크기가 변하지 않음
코드 영역 ( = 텍스트 영역)
- 실행할 수 있는 코드, 기계어로 이루어진 명령어 저장
- 데이터가 아닌 CPU가 실행할 명령어가 담기기 때문에, 쓰기가 금지된 영역(read-only)
(프로그램은 데이터와 명령어로 이루어져 있음. 프로그램을 구성하는 명령어, 실제로 프로그램이 순차적으로 실행해야 하는 명령어가 저장되는 공간이기에 갑자기 바뀔 일은 없음)
데이터 영역
- 잠깐 썼다가 없앨 데이터가 아닌 프로그램이 실행되는 동안 유지할 데이터 저장
- ex) 전역변수
동적 할당 영역
- 스택 영역과 힙 영역
- 동적으로 크기가 변할 수 있음(가변적)
힙 영역
- 프로그램을 만드는 사용자, 즉 프로그래머가 직접 할당할 수 있는 저장 공간
- 참고 )
- 메모리를 할당 한 뒤 사용을 마치면 할당한 이 메모리 공간을 반환해야함
- 요즘은 프로그래밍 언어가 대신 반환해주는데 이것을 garbage collection 이라고 함
- C언어와 같은 옛날 프로그래밍 언어는 가비지 콜렉션 기능이 없어서 직접 메모리를 반환해야 함
- 반환하지 않으면 계속 메모리 공간을 차지하면서 메모리 낭비를 초래함(메모리 누수 = 메모리 리크)
스택 영역
- 데이터가 일시적으로 저장되는 공간
- (데이터 영역에 담기는 값과는 달리) 잠깐 쓰다가 말 값들이 저장되는 공간
- ex. 매개 변수, 지역 변수
힙 영역과 스택 영역의 크기는 가변적
- 일반적으로 힙 영역은 낮은 주소 → 높은 주소로 할당
- 일반적으로 스택 영역은 높은 주소 → 낮은 주소로 할당
- 영역 충돌, 주소가 겹칠 일이 거의 없음

프로세스 상태
* 운영체제마다 조금씩 차이가 있지만, 대표적으로는~
- 생성 상태
- 준비 상태
- 실행 상태
- 대기 상태
- 종료 상태
상태 자세히 보기
- 생성 상태 (New State)
- 이제 막 메모리에 적재되어 PCB를 할당 받은 상태
- 준비가 완료되었다면 준비 상태로 바뀜
- 준비 상태 (Ready State)
- 당장이라도 CPU를 할당 받아 실행할 수 있지만, 자신의 차례가 아니기에 기다리는 상태
- 자신의 차례가 된다면 실행 상태로 바뀜(=디스패치, dispatch)
- 실행 상태 (Running State)
- CPU를 할당 받아 실행 중인 상태
- 할당된 시간 모두 사용 시(타이머 인터럽트 발생 시) 준비 상태로 바뀜
- 실행 도중 입출력 장치를 사용하면 입출력 작업이 끝날 때까지 대기 상태로 존재
- 대기 상태 (Block State)
- 프로세스가 실행 도중 입출력장치를 사용하는 경우
- 입출력 작업은 CPU에 비해 느리기 때문에 이 경우 대기 상태로 접어듬(CPU를 계속 점거하는 것은 낭비니까)
- 입출력 작업이 끝나면(입출력 완료 인터럽트를 받으면) 준비 상태로 바뀜
- 종료 상태 (Terminated State)
- 프로세스가 종료된 상태
- PCB, 프로세스의 메모리 영역 정리

프로세스 계층 구조
* 윈도우 운영체제는 프로세스를 계층적으로 관리하지 않음. 하지만 많은 개발자들이 사용하는 리눅스나 맥OS, 유닉스 등은 프로세스를 계층적으로 운영하기 때문에 알아둬야 함.
- 프로세스는 실행 도중 (시스템 호출을 통해) 또다른 프로세스 생성 가능
- 이때 새 프로세스를 생성한 프로세스를 부모 프로세스(parent process)
- 부모 프로세스에 의해 생성된 프로세스를 자식 프로세스(child process)
- 부모 프로세스와 자식 프로세스는 별개의 프로세스이므로 각기 다른 PID를 가짐
- 일부 운영체제에서는 자식 프로세스 PCB에 부모 프로세스 PID(PPID, Parent PID)를 명시하기도 함
- 자식은 자식을 낳고, 또 그 자식은 자식을 낳고...
- 이 과정이 반복되며 프로세스의 계층적인 구조가 형성됨


최초의 프로세스

프로세스 생성 기법
부모 프로세스는 자식 프로세스를 어떻게 만들어 내고, 자식 프로세스는 어떻게 자신만의 코드를 실행할까?
=> 복제와 옷 갈아입기
*Windows 운영체제와는 큰 관련이 없음
fork와 exec
- 부모 프로세스는 fork 시스템 호출을 통해 자신의 복사본을 자식 프로세스로 생성
- 자식 프로세스는 exec 시스템 호출을 통해 자신의 메모리 공간을 다른 프로그램으로 교체
fork 시스템 호출
- 복사본(=자식 프로세스) 생성
- 부모 프로세스의 자원 상속

exec 시스템 호출
- 메모리 공간을 새로운 프로그램으로 덮어쓰기
- 코드/데이터 영역은 실행할 프로그램 내용으로 바뀌고 나머지 영역은 초기화

- 예시
- 사용자가 bash shell 에서 ls라고 하는 명령어를 입력
- bash shell 프로세스는 fork 시스템 호출, 복제본 프로세스(자식 프로세스) 생성
- exec 시스템 호출을 통해 ls라고 하는 명령어를 실행하기 위한 프로세스로 전환됨
- 프로세스를 생성하고, 계층 구조를 이루는 과정은 fork 시스템 호출과 exec 시스템 호출이 반복되는 과정
- 물론 fork 시스템 호출까지만 하고 exec 시스템 호출을 하지 않는 경우도 있음


스레드(thread)
- 프로세스를 구성하는 실행 흐름의 단위
- 하나의 프로세스는 하나 이상의 스레드를 가질 수 있다

- 단일 스레드 프로세스
- 실행 흐름이 하나인 프로세스
- 멀티 스레드 프로세스
- 실행 흐름이 여러 개인 프로세스
- 프로세스를 이루는 여러 명령어 동시 실행 가능


스레드의 구성 요소
- 스레드 ID, 프로그램 카운터를 비롯한 레지스터 값, 스택 등 실행에 필요한 최소한의 정보

- 3개의 쓰레드로서 병행 실행되는 프로세스
- 스레드마다 각기 다른 스택 영역과 프로그램 카운터를 가지고 있어서 스레드마다 서로 각기 다른 프로그램에 있는 부분들을 실행할 수 있음
- 프로세스를 이루는 각각의 스레드들은 프로세스의 자원을 공유하면서 실행됨
- 스레드1,2,3 모두 똑같은 코드 영역, 데이터 영역을 공유하고 있음
- 프로세스가 어떤 파일을 열었다면 각각의 스레드는 모두 그 열린 파일에 접근할 수 있음

참고)
많은 운영체제에서는 프로세스와 스레드를 구분해서 사용하지만,
리눅스에서는 프로세스와 스레드를 똑같은 실행의 문맥으로 생각함
그래서 프로세스와 스레드 대신에 태스크라는 용어로 사용함
실제로도 CPU한테 처리해야 될 작업을 전달 할 때
요즘 운영체제는 프로세스를 통채로 전달하기보단
스레드 단위로 CPU를 할당받아서 사용하고 할당을 해제하는 식
즉, 스레드 단위로 전달하는 경우가 많음
아직까지 전통적인 관점의 전공서에서는
CPU에게 처리해야 할 작업을 전달할 때
프로세스 단위로 전달한다고 되어있지만,
실제로는 스레드 단위라는 걸 참고로만 알아두면 됨!
멀티 프로세스와 멀티 스레드
동일한 작업을 수행하는
단일 스레드 프로세스 여러 개
vs
하나의 프로세스를
여러 스레드로 실행

멀티 프로세스
- 프로세스를 fork하면 코드/데이터/힙 영역 등 모든 자원이 복제되어 저장됨
- 저장된 메모리 주소를 제외하면 모든 것이 동일한 프로세스 두 개가 통째로 메모리에 적재
- fork를 세번 네번 하면 메모리에는 같은 프로세스가 통째로 세개 네개 적재됨
- 참고)
fork 직후 같은 프로세스를 통째로 메모리에 중복 저장하지 않으면서 동시에 프로세스끼리 자원을 공유하지 않는 방법도 있음 (쓰기 시 복사, copy on write)
- 참고)

멀티 스레드
- 스레드들은 각기 다른 스레드 ID, (별도의 실행을 위해 꼭 필요한) 프로그램 카운터 값을 포함한 레지스터 값, 스택을 가질 뿐 프로세스가 가지는 자원을 공유함
- 그렇기 때문에 자원이 변경된다 해도 각각의 스레드들은 그 변경을 바로바로 알아챌 수 있음
- 하지만 하나의 스레드에 문제가 생기면, 자원을 공유하고 있기 때문에 전체 프로세스에 문제가 생길 수 있음


정리
- 프로세스 끼리는 자원을 공유하지 않는다 → 남남처럼 독립적으로 실행된다
- 스레드는 프로세스의 자원을 공유한다 → 협력과 통신에 유리하다. 하지만 때때로 문제가 생길 수 있다
참고 : 프로세스 간 통신(IPC, Inter Process Communication)
- 프로세스끼리는 자원을 공유하지 않음
- 하지만 프로세스 간에도 자원을 주고 받을 수 있는데, 이를 프로세스 간 통신(IPC)이라고 함
- 파일을 통한 프로세스 간 통신
- 프로세스 A가 hello.txt라고 하는 텍스트 파일에 새로운 값 쓰기
- 프로세스 B가 hello.txt 파일 읽기
- hello.txt 파일을 통해 서로 통신을 주고 받았다 할 수 있음
- 공유 메모리를 통한 프로세스 간 통신
- 공유 메모리에 전역변수 name 값을 저장
- 프로세스 A가 name에다가 어떤 값 입력
- 프로세스 B는 그 공유 메모리 안에 name 변수를 읽음
- 이외에도 소켓, 파이프 등 다양한 통신 기법들이 있음
출처 : 혼자 공부하는 컴퓨터구조 + 운영체제 (저자 강민철)
'취업역량강화 > 컴퓨터공학' 카테고리의 다른 글
| [운영체제] CPU 스케줄링과 스케줄링 알고리즘 (0) | 2026.02.17 |
|---|---|
| [운영체제] 파이썬으로 프로세스와 스레드 다루기 (0) | 2026.02.15 |
| [운영체제] 운영체제(정의, 핵심기능, 커널, 이중모드와 시스템 호출) (0) | 2026.02.11 |
| [컴퓨터 구조] 입출력 장치(장치 컨트롤러와 장치 드라이버, 다양한 입출력 방법) (0) | 2026.02.09 |
| [컴퓨터 구조] 보조기억장치 (보조기억장치, RAID의 정의와 종류) (0) | 2026.02.07 |