프로세스 개요
보통 '실행 중이 프로그램'을 프로세스라고 합니다. 이 프로세스라는 프로그램은 메모리에 적재되고 실행되어야 프로세스라 불릴 수 있고 이 과정을 '프로세스를 생성한다'라고 표현합니다.
*우리가 눈으로 볼 수 있는 공간에서 실행되는 프로세스를 포그라운드 프로세스 사용자가 보지 못하는 공간에서 실행되는 프로세스를 백그라운드 프로세스라고 합니다.
프로세스 제어 블록
모든 프로세스는 실행을 위해 CPU를 필요로 하지만, CPU 자원은 한정되어 있습니다. 떄문에 프로세스는 차례대로 돌아가며 한정된 시간을 이용합니다. 그리고 운영체제에서는 이러한 실행 순서와 자원 배분을 관리합니다. 이를 위해 운영체제는 프로세스 제어 블록(이하 PCB)을 이용합니다.
프로세스 제어 블록은 프로세스를 식별하기 위해 꼭 필요한 정보들이 저장되며 커널 영역에서 생성됩니다. 그렇다면 PCB에는 어떤 정보들이 담기는지 알아보겠습니다.
프로세스 ID
프로세스 ID(이하 PID)는 특정 프로세스를 식별하기 위해 부여하는 고유한 번호입니다. 같은 일을 수행하는 프로그램이라 할지라도 두 번 실행하면 PID가 다른 두 개의 프로세스가 생성됩니다.
레지스터 값
프로세스는 자기 차례에 이전까지 진행했던 작업을 이어야 하기에 진행했던 작업들, 프로그램 카운터를 비롯한 레지스터 값들의 정보를 가지고 있습니다.
프로세스 상태
현재 프로세스가 입출력장치를 사용하기 위해 기다리고 있는 상태인지, CPU를 사용하기 위해 기다리는 상태인지 등등 프로세스 상태 정보가 저장됩니다.
CPU 스케줄링 정보
프로세스가 언제, 어떤 순서로 CPU를 할당받을지에 대한 정보도 PCB에 기록됩니다.
메모리 관리 정보
프로세스마다 메모리에 저장되는 위치가 다르기에 이에 다한 주소도 저장되어야 합니다. PCB에는 베이스 레지스터, 한계 레지스터 값과 같은 정보들이 담깁니다. 또한 페이지 테이블 정보도 담깁니다.
사용한 파일과 입출력장치 목록
프로세스가 실행 과정에서 특정 입출력장치나 파일을 사용하면 PCB에 내용이 명시됩니다.
문맥 교환
프로세스 A가 운영체제로부터 CPU를 할당받아 실행되다가 프로세스 B에 CPU 사용을 양보한다고 가정해 보겠습니다. 이런 상황에서 프로세스 A는 위에서 언급한 정보들을 백업해야 하고 이를 문맥이라고 합니다.
즉, 기존 프로세스의 문맥을 PCB에 백업하고, 새로운 프로세스를 실행하기 위해 문맥을 PCB로 부터 복구하여 새로운 프로세스를 실행하는 것을 문맥 교환이라 합니다.
프로세스 메모리 영역
프로세스가 생성되면 커널 영역에는 PCB가 생성됩니다. 그렇다면 사용자 영역에는 어떤 것이 배치되는지 알아보겠습니다.
코드 영역
코드 영역은 텍스트 영역이라고도 부릅니다. 이곳에는 실행할 수 있는 코드 즉 기계어로 이루어진 명령어가 저장됩니다. 코드 영역에는 데이터가 아닌 CPU가 실행할 명령어가 담겨 있기 때문에 쓰기가 금지되어 있습니다. 다시 말 해 코드 영역은 읽기 전용 공간입니다.
데이터 영역
데이터 영역은 잠깐 썼다가 없앨 데이터가 아닌 프로그램 실행되는 동안 유지할 데이터가 저장되는 공간입니다. 전역 변수가 대표적입니다.
코드 영역과 데이터 영역은 크기가 변하지 않는 영역으로 정적 할당 영역이라고도 부릅니다. 반면 힙 영역과 스택 영역은 크기가 변할 수 있는 영역으로 동적 할당 영역이라고도 부릅니다.
힙 영역
힙 영역은 프로그램을 만드는 사용자, 즉 프로그래머가 직접 할당할 수 있는 저장 공간입니다. 프로그래밍 과정에서 힙 영역에 메모리 공간을 할당했다면 언젠가는 해당 공간을 반환해야 합니다.
만약 메모리 공간을 반환하지 않는다면 할당한 공간은 메모리 내에 계속 남아 메모리 낭비를 초래합니다. 이를 메모리 누수라고 합니다.
스택 영역
스택 영역은 데이터를 일시적으로 저장하는 공간입니다. 이런 데이터는 대표적으로 매개 변수, 지역 변수가 있습니다.
힙 영역과 스택 영역은 실시간으로 그 크기가 변할 수 있기 때문에 동적 할당 영역이라고 부릅니다. 그래서 힙 영역은 메모리의 낮은 주소에서 높은 주소로 할당되고, 스택 영역은 높은 주소에서 낮은 주소로 할당됩니다. 그래야 데이터가 쌓여도 새롭게 할당되는 주소가 겹치지 않기 때문입니다.
프로세스 상태와 계층 구조
프로세스 상태
프로세스는 여러 상태를 거치며 실행됩니다. 그리고 운영체제는 프로세스의 상태를 PCB를 통해 인식하고 관리합니다. 프로세스의 상태를 표현하는 방식은 대표적으로 아래와 같습니다.
생성 상태
프로세스를 생성 중인 상태를 생성 상태(new)라고 합니다. 이제 막 메모리에 적재되어 PCB를 할당 받은 상태를 말하며 실행되지 않고 준비 상태가 되어 CPU의 할당을 기다립니다.
준비 상태
준비 상태(ready)는 CPU를 할당받기 전 기다리고 있는 상태입니다. 준비 상태 프로세스는 차례가 되면 CPU를 할당 받아 실행 상태가 됩니다.
*준비 상태인 프로세스가 실행 상태로 전환되는 것을 디스패치(dispatch)라고 합니다.
실행 상태
실행 상태(running)은 CPU를 할당받아 실행 중인 상태를 의미합니다. 실행 상태인 프로세스가 할당된 시간을 모두 사용한다면 준비 상태가 되고, 실행 도중 입출력장치를 사용해야 한다면 해당 작업이 끝날 때까지 대기 상태가 됩니다.
대기 상태
입출력 작업은 CPU에 비해 처리 속도가 느리기에, 입출력 작업을 요청한 프로세스는 입출력장치가 입출력을 끝낼 때까지 기다려야합니다. 이렇게 입출력장치의 작업을 기다리는 상태를 대기 상태(blocked)라고 합니다.
종료 상태
종료 상태(terminated)는 프로세스가 종료된 상태입니다. 프로세스가 종료되면 운영체제는 PCB와 프로세스가 사용한 메모리를 정리합니다.
프로세스 계층 구조
프로세스는 실행 도중 시스템 호출을 통해 다른 프로세스를 생성할 수 있습니다. 이때 새 프로세스를 생성한 프로세스를 부모 프로세스, 부모 프로세스에 의해 생성된 프로세를 자식 프로세스라고 합니다.
이들은 엄연히 다른 프로세스이기에 각기 다른 PID를 가지며 일부 운영체제에서는 자식 프로세스의 PCB에 부모 프로세스의 PID인 PPID를 기록하기도 합니다.
부모 프로세스가 자식 프로세스를 생성할 수 있듯이 자식 프로세스도 자신의 자식 프로세스를 생성할 수 있습니다. 이를 운영체제에서는 계층적인 구조로써 관리하며 그 과정에서 생겨난 트리 구조를 프로세스 계층 구조라고 합니다.
프로세스 생성 기법
부모 프로세스가 자식 프로세스를 어떻게 만들어 내고, 자식 프로세스는 어떻게 자신만의 코드로 실행하는지 알아보겠습니다. 결론부터 말하면 복제와 옷 갈아입기를 통해 실행됩니다.
- 부모 프로세스는 fork를 통해 자신의 복사본을 자식 프로세스로 생성해냅니다.
- 만들어진 복사본(자식 프로세스)은 exec를 통해 자신의 메모리 공간을 다른 프로그램으로 교체합니다.
스레드
스레드는 실행의 단위입니다. 정확히는 스레드란 프로레스를 구성하는 실행의 흐름 단위입니다. 그리고 하나의 프로세스는 여러 개의 스레드를 가질 수 있고, 스레드를 이용하여 하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다.
프로세스와 스레드
본래 하나의 프로세스는 한 번에 하나의 일만 처리했고 '실행의 흐름 단위가 하나'라는 점에서 이를 단일 스레드 프로세스라고 불렀습니다.
하지만 스레드라는 개념이 도입되면서 하나의 프로세스가 한 번에 여러 일을 동시에 처리할 수 있게 되었습니다. 즉, 프로세스를 구성하는 여러 명령어를 동시에 실행할 수 있게 되었습니다.
아래 그림을 보면서 더 자세히 알아보겠습니다. 각각의 스레드는 프로세스 내에서 각기 다른 스레드 ID, 프로그램 카운터 값을 비롯한 레지스터 값, 스택으로 구성됩니다.
여기서 중요한 점은 스레드들은 실행에 필요한 최소한의 정보만을 유지한 채 프로세스 자원을 공유하며 실행된다는 점입니다.
멀티프로세스와 멀티스레드
여러 프로세스를 동시에 실행하는 것을 멀티프로세스, 여러 스레드로 프로세스를 동시에 실행하는 것을 멀티스레드라고 합니다.
이 둘의 차이는 프로세스끼리는 기본적으로 자원을 공유하지 않지만, 스레드끼리는 같은 프로세스 내의 자원을 공유한다는 점입니다.
그래서 기본적으로 프로세스는 자원을 공유하지 않기에 메모리를 많이 잡아먹습니다. 반면 스레드는 자원을 공유하기에 메모리를 효율적으로 사용할 수 있습니다. 또한 협력과 통신에 유리합니다.
그러나 공유한다는 특성이 때로는 단점이 될 수 있습니다. 가장 큰 문제는 멀티스레드 환경에서는 하나의 스레드에 문제가 생기면 프로세스 전체에 문제가 생길 수 있다는 점입니다.
*프로세스끼리는 '기본적으로' 자원을 공유하지 않지만, 프로세스끼리도 프로세스 간 통신(이하 IPC)를 통해 자원을 공유할 수 있습니다. 보통 파일을 통한 프로세스 간 통신으로 볼수 있으며, 프로세스는 공유 메모리라는 메모리 영역을 두어 이를 주고받습니다.
'시리즈 > 운영체제' 카테고리의 다른 글
[운영체제] 가상 메모리 (0) | 2025.02.17 |
---|---|
[운영체제] 교착 상태 (DeadLock) (0) | 2025.02.13 |
[운영체제] 프로세스 동기화 (0) | 2025.02.10 |
[운영체제] CPU 스케줄링 (0) | 2025.02.09 |
[운영체제] 운영체제 시작하기 (0) | 2025.02.04 |