10. 프로세스와 스레드
1. 프로세스 개요
컴퓨터 내 프로세스에는 사용자가 알 수 없는 프로세스가 많이 실행된다.
포그라운드 프로세스 : 사용자가 알 수 있는 프로세스
백그라운드 프로세스 : 사용자가 알 수 없는 프로세스
데몬(유닉스), 서비스(윈도우) : 사용자와 상호작용하지 않고 묵묵하게 동작하는 백그라운드 프로세스
프로세스 제어 블록(PCB : Process Control Block)
모든 프로세스는 실행을 위해서 CPU 를 필요로 하지만, CPU 자원은 한정되어 있고 한정된 시간 만큼만 사용할 수 있다.
운영체제는 빠르게 번갈아 수행되는 프로세스의 실행 순서를 관리하고, CPU 를 비롯한 자원을 분배를 해야하는데, 이때 사용 되는 자료구조를 프로세스 제어 블록(PCB : Process Control Block) 이라고 부른다. -> 프로세스 제어 블록은 프로세스와 관련된 정보을 저장하는 자료구조이다. -> PCB 는 커널영역에 생성된다.
PCB 는 프로세스 생성 시에 만들어지고, 실행이 끝나면 폐기된다.
프로세스 제어 블록에 저장되는 정보
프로세스 ID : 프로세스를 식별하기 위한 고유 번호
레지스터 값 : 프로세스가 일시적으로 실행이 멈추고 다른 프로세스가 실행되는 경우가 있을 수 있습니다. 이런 경우 프로세스는 이전까지 사용되었던 레지스터 값들을 모두 저장해야 합니다. 왜냐하면 다음에 다시 실행될 때 이전의 상태를 복원하여 이전에 진행했던 작업을 그대로 이어나가야 하기 때문입니다.
프로세스 상태 : 현재 프로세스의 상태
CPU 스케줄링 정보 : 프로세스가 언제, 어떤 순서로 CPU 를 할당받을지에 대한 정보
메모리 관리 정보 : 프로세스가 메모리 어느 주소에 저장되어 있는지에 대한 정보
사용한 파일과 입출력장치 목록
문맥 교환(Context Switching)
하나의 프로세스 수행을 재개하기 위해 기억해야 할 정보(PCB 내부 문맥)를 문맥(Context) 이라고 한다.
이처럼 기존 프로세스의 문맥을 PCB 에 백업하고, 새로운 프로세스를 실행하기 위해 문맥을 PCB 로부터 복구하여 새로운 프로세스를 실행하는 것을 문맥 교환(Context Switching) 이라고 부른다.
문맥 교환이 자주 일어나면 프로세스는 그만큼 빨리 번갈아 가며 수행되기 때문에, 사용자 입장에서는 프로세스들이 동시에 실행되는 것처럼 보인다.
프로세스 메모리 영역
코드 영역
코드 영역(텍스트 영역) 은 말 그대로 코드가 담겨있는 영역으로, 즉 기계어로 이루어진 명령어(어셈블리어)가 저장된다.
코드 영역은 데이터가 아닌 CPU 가 실행할 명령어가 담겨 있기 때문에, 쓰기가 금지되어 있다. -> ONLY READ
데이터 영역
프로그램이 실행되는 동안 유지할 데이터가 저장되는 공간으로 전역 변수(or static 변수)가 대표적이다.
코드 영역과 데이터 영역은 그 크기가 변하지 않는다. -> 프로그램을 구성하는 명령어들이 갑자기 바뀔 일이 없으니, 코드 영역이 바뀔 일은 없다. -> 데이터 영역에 저장될 내용은 프로그램이 실행되는 동안에만 유지되기에, 데이터 영역이 바뀔 일은 없다.
위와 같이 변하지 않는 특성을 가진 코드 영역, 데이터 영역은 정적 할당 영역이라고 부른다.
힙 영역과 스택 영역 같이 변하는 영역을 동적 할당 영역이라고 부른다.
힙 영역
프로그래머의 명령에 의해 OS 가 할당해주는 저장 공간으로 메모리 내에 다른 프로세스와 공유가 가능한 공간이다.
메모리 공간을 반환하지 않는다면 할당한 공간은 메모리 내에 계속 남아 메모리 낭비를 초래한다. -> 이런 문제를 메모리 누수(memory leak)라고 한다.
스택 영역
프로그래머가 직접 할당할 수 있는 저장 공간으로 프로세스 내에 한정된 공간이다.
스택 영역은 데이터를 일시적으로 저장할 수 있는 공간으로 한정된 메모리보다 많은 메모리를 사용할 경우, stackoverflow 에러가 발생한다.
스택 영역은 프로그램 실행 파일에 할당되는 공간으로 생각하면 된다. -> 실행 파일에 대한 특별한 설정이 없다면, 하나에 실행 파일에 대해서 1MB 가 할당된다.
2. 프로세스 상태와 계층 구조
운영체제는 동시에 실행되는 수많은 프로세스를 계층적으로 관리한다.
프로세스 상태
생성 상태(ing)
프로세스를 생성 중인 상태를 생성 상태라고 한다.
이제 막 메모리에 적재되어 PCB 를 할당받은 상태를 의미한다.
준비 상태
당장이라도 CPU 를 할당받아 실행할 수 있지만, 아직 자신의 차례가 아니기에 기다리고 있는 상태이다.
실행 상태
CPU 를 할당받아 실행하고 있는 상태를 의미한다.
실행 상태인 프로세스는 할당된 시간 동안만 CPU 를 사용할 수 있다. -> 이 때 프로세스가 할당된 시간으로 모두 사용한다면(타이머 인터럽트가 발생하면) 다시 준비 상태가 되고, -> 실행 도중 입출력장치를 사용하여 입출력 장치의 작업이 끝날 때까지 기다려야 한다면 대기 상태가 된다.
대기 상태
프로세스 작업 도중 입출력장치를 사용하는 경우, 입출력 작업은 CPU 에 비해 처리 속도가 느리기 때문에, 입출력장치의 입출력이 끝날 때까지 기다려야 하는 상태를 의미한다.
입출력 작업이 완료되면 해당 프로세스는 다시 준비 상태로 CPU 할당을 기다린다.
종료 상태
프로세스 계층 구조
프로세스는 실행 도중 시스템 호출을 통해 다른 프로세스를 생성할 수 있다. -> 새 프로세스를 생성한 프로세스를 부모 프로세스 -> 부모 프로세스에 의해 생성된 프로세스를 자식 프로세스
부모 프로세스와 자식 프로세스는 엄연히 다른 프로세스이기에 각기 다른 PID 를 가진다. -> 일부 운영체제에서는 자식 프로세스의 PCB 에 부모 프로세스의 PID 인 PPID 가 기록되기도 한다.
이런 형식으로 생성되는 프로세스 트리구조를 프로세스 계층 구조라부른다.
3. 스레드
스레드는 프로세스를 구성하는 실행의 흐름 단위이다. -> 하나의 프로세스는 여러 개의 스레드를 가질 수 있다.
프로세스와 스레드
전통적인 관점에서 하나의 프로세스는 한 번에 하나의 일만을 처리했다. -> 프로세스가 하나의 실행 흐름을 가지고 한 번에 하나의 부분만 실행되는 프로세스를 가정했다.
하지만 스레드의 개념이 도입 되면서 하나의 프로세스가 한 번에 여러 일을 동시에 처리할 수 있게 되었다. -> 즉, 프로세스가 여러개의 실행 흐름을 가지고, 여러 명령어를 동시에 실행시킬 수 있게 되었다.
스레드는 프로세스 내에서 각기 다른 스레드 ID, 프로그램 카운터 값을 비롯한 레지스터 값, 스택으로 구성된다. -> 스레드마다 각기 다른 레지스터 값, 스택을 가지고 있기 때문에, 각기 다른 코드를 실행할 수 있다.
여기서 중요한 점은, 프로세스의 스레드들은 실행에 필요한 최소한의 정보만을 유지한 채 프로세스 자원을 공유하며 실행된다는 점이다. -> 프로세스 자원을 공유한다는 것이 스레드의 핵심이다! -> 스레드는 프로세스의 코드, 데이터, 힙 영역을 공유한다!
정리하면, 스레드마다 스레드ID, 레지스터 값, 스택은 고유하지만 코드, 데이터, 힙 영역을 공유한다.
멀티프로세스와 멀티스레드
컴퓨터는 실행 과정에서 여러 프로세스가 동시에 실행될 수 있고, 그 프로세스를 이루는 스레드는 여러 개 있을 수 있다. -> 이때 여러 프로세스를 동시에 실행하는 것을 멀티프로세스, -> 여러 스레드로 프로세스를 동시에 실행하는 것을 멀티스레드라고 한다.
동일한 작업을 수행하는 단일 스레드 프로세스를 여러 개를 실행하는 것 / 하나의 프로세스를 여러 스레드로 실행하는 것은 무엇이 다른가?
가장 큰 차이는, 프로세스는 기본적으로 자원을 공유하지 않지만, 스레드 끼리는 같은 프로세스 내의 자원을 공유한다는 점이다. -> 예를들어, 프로세스 두 개를 동시에 실행한다면 코드, 데이터, 힙 영역을 비롯한 모든 자원이 복제되어 메모리에 적재된다. (잘 설계되지 않은 멀티프로세스는 메모리 낭비를 초래한다) -> 반대로 멀티스레드는 메모리 복제가 이루어지지 않아 메모리를 효율적으로 사용할 수 있다.
하지만 메모리 공간을 공유한다는 특징은 단점이 될수도 있는데, 멀티프로세스 환경에서는 하나의 프로세스에 문제가 생겨도 다른 프로세스에 영향이 적거나 없지만, 멀티스레드 환경에서는 하나의 스레드에 문제가 생기면 프로세스 전체에 문제가 생길 수 있다.
Last updated