프로세스와 스레드

프로세스

우리는 인텔리제이, VS Code 같은 IDE를 실행할 때, 화면에 있는 아이콘을 클릭한다.
이 때, 우리가 실행하는 것은 프로그램이다. 프로그램은 휘발되지 않고, 영구적으로 저장되는
하드 디스크에 저장되어 있는 데이터 모음이다. 프로그램 자체는 소프트웨어로서 어떠한 능력을
발휘하지 않는다. 우리가 IDE를 통해 코딩을 하면서 다양한 기능들을 사용할 수 있는 것은
프로그램이 아닌 프로세스이다.

프로세스는 프로그램을 구성하는 여러 코드들을 CPU(코어)가 수행할 수 있도록 메모리를
할당받으며, 운영체제 안에서 실행되는 프로그램을 프로세스라고 한다.

ryySJqf.png|536

이처럼 하나의 운영체제 안에 여러 프로그램을 실행했을 때, 각각이 프로세스 단위로 존재하게 된다.
그림에서 알 수 있듯이, 각 프로세스는 고유한 메모리 공간을 갖고 있다.
중요한건 프로세스 별로 독립된 메모리 공간을 가지며, 다른 프로세스의 메모리에 접근할 수 없다. (운영체제의 역할 중 하나)
이것이 시사하는 바는 다음과 같다. 그림에서 유튜브 뮤직 프로세스에 문제가 생기더라도
인텔리제이 프로세스에는 영향을 주지 않는다. 이처럼 각 프로세스는 서로에게 영향을 주지 않고
독립적인 생명주기를 갖는다. 물론 이건 당연하게 되는 것이 아니라 운영체제의 도움 덕분이다.

프로세스 구조

코드

프로그램이 실행되려면 먼저 프로세스 상태가 되어야 한다. 그리고 프로그램을 구성하는 코드들을
순차적으로 실행함으로써 비로소 구현한 기능들이 동작한다. 이 때, 프로그램을 구성하는 코드들이 저장되는 공간이 코드 영역이다.

자바에서 힙 메모리는 인스턴스가 생성됐을 때, 해당 인스턴스의 주소 값이 저장되는 공간이다.
프로세스의 힙 메모리도 이와 마찬가지로 동적으로 생성되어 할당되는 주소 값이 저장되는 공간이다.

데이터

코드에서 전역 변수 및 정적 변수가 저장되는 메모리 공간이다. 해당 그림에서 기타에 해당한다.

스택

메서드(함수)를 호출했을 때, 생성되는 지역 변수와 반환되는 주소가 저장되는 공간으로 이는 프로세스가 아닌 스레드의 영역에 속한다. (이후 그림으로 다시 소개하겠다.)

프로세스를 구성하는 메모리 영역의 이름과 특징을 확인해보았다. 그런데 생각보다 이들의 역할이 이름과 잘 매칭이 되고 있다.

코드는 말 그대로 프로그램을 구성하는 코드를 저장한다. 힙은 동적으로 할당되는 주소 값을 저장한다. 데이터는 코드 실행에 필요한 데이터에 해당하는 전역 변수 및 정적 변수를 저장한다.

스레드

프로세스의 메모리 영역을 살펴보면서 스택 메모리는 프로세스가 아닌 스레드에 속한다고 하였다.
그말은 스레드라는 것은 프로세스 내에 속하는 존재라는 것이다.

우리가 작성한 코드 혹은 특정 프로그램을 실행함으로써 코드가 실행되는 기본적인 단위가
바로 스레드이다. 여기서 혼동하면 안되는 건 실제 코드를 실행하는 실질적인 주체는 CPU(코어)라는 것이다! CPU는 프로세스 내에 존재하는 스레드의 코드를 실행하는 것이다.

하나의 프로세스에는 여러 스레드가 존재할 수 있으며, 여러 스레드들은 프로세스가 갖고 있는 메모리 영역(코드, 힙, 데이터)을 공유하며 사용할 수 있다.

프로세스를 만드는 것과 스레드를 만드는 것 중 어떤 것이 더 많은 비용을 소모할까?
프로세스는 기본적으로 코드, 힙, 데이터가 필요하다. 하지만 스레드는 각 스레드별로 존재하는 스택 메모리만 있으면 된다. 따라서 프로세스보다 스레드를 생성하는 것이 더 간편하고 가벼우며,
하나의 프로세스에는 여러 스레드가 존재할 수 있다.

etc-image-1

스레드들은 자신이 속한 프로세스의 메모리 영역을 공유할 수 있다. (코드, 힙, 데이터)
하지만 각 스레드별로 갖고 있는 스택 메모리는 서로 공유할 수 없다.

단일 스레드와 멀티 스레드

우리가 작성한 자바 클래스의 main 메서드를 실행하면, CPU가 하나의 스레드를 통해 코드를 순차적으로 실행할 것이다. 그러나 스레드가 두 개라면? 두 개의 스레드를 사용해서 코드를 실행할 것이다.

스레드가 많다면 그만큼 프로그램에 작성된 코드를 한 번에 실행할 수 있는 범위가 넓어지는 것이다. 이를 잘 활용하면 하나의 프로그램에서 여러 기능들을 수행할 수 있다.

현재 이 글을 작성하는데 사용하고 있는 옵시디언도 단순 글을 작성하는 것뿐만 아니라
여러 플러그인들이 동작하고 있다. 이 또한 옵시디언이라는 프로세스에 여러 스레드가
존재하기에 가능한 것이다.

강의에서는 유튜브를 멀티 스레드의 예시로 소개하였다.

EwPlo1b.png|611

우리는 유튜브 숏츠 영상을 보면서 댓글을 달 수도 있다.
이 때, 유튜브 숏츠를 재생시키는 스레드와 댓글을 작성할 수 있는 스레드가 존재하는 것이다.

스레드와 스케줄링

jyUGOgX.png|671

실제 프로그램의 실행 단위는 스레드라고 하였다. 그리고 이 실행을 담당하는 것은 CPU(코어)다.
따라서 CPU는 각 프로세스에 존재하는 스레드를 하나씩 가져와서 실행한다. (코어 1개 기준)

여기서 프로세스는 각 스레드가 실행될 수 있도록 자원(메모리 - Code/Heap/기타)을 제공하는 컨테이너 역할을 한다.

그림처럼 1개의 코어는 유튜브 뮤직 프로세스의 스레드에 존재하는 코드를 일부 실행하고, 인텔리제이 프로세스의 스레드 중 한 개를 선택해 해당 스레드에 존재하는 코드를 일부 실행할 것이다.

이처럼 여러 프로세스와 여러 스레드가 존재할 때, CPU는 어떻게 스레드를 번갈아 실행할 수 있는걸까?

스케줄링 큐

운영체제는 스레드들의 작업 순서를 관리할 수 있는 스케줄링 큐를 구현하여 갖고 있다.
따라서 작업되어야 할 스레드들은 이 스케줄링 큐에 들어가며 먼저 들어온 스레드부터 처리된다.

etc-image-4

위 그림처럼 맨 앞에 있는 스레드 C가 실행되고, 그 다음 순서인 스레드 B가 실행될 것이다.

만약, 코어가 두 개 이상이라면 어떻게 될까? 그러면 물리적으로 두 개 이상의 스레드가 동시에 병렬적으로 실행될 것이다.

etc-image-5

코어가 두 개일 때 스케줄링 큐에 있는 스레드가 훨씬 빨리 비워짐을 알 수 있다.

용어 정리

멀티 태스킹과 스케줄링

멀티 태스킹은 하나의 코어가 여러 스레드를 수행하고자 할 때, 각각 번갈아 수행하는 것을 말한다.
이 때, 운영체제는 스케줄링 기법을 사용하고, 각각의 스레드를 스케줄링 큐에 넣어 관리한다.

프로세스와 스레드

프로세스는 하나의 프로그램이 운영체제에 의해 실제 실행되는 단위를 뜻한다. 각 프로세스는 독립적인 메모리를 갖게 되며, 운영체제에서 독립된 실행 단위로 취급된다.

스레드는 하나의 프로세스에 존재하며, 하나의 프로세스는 여러 개의 스레드를 생성할 수 있다. 여러 스레드는 하나의 프로세스 메모리 자원을 공유하며, 각 스레드는 별도의 스택 메모리를 갖고 있다. 스레드는 프로세스의 코드 영역에 있는 프로그램 코드를 가져가게 되며, 이를 CPU(코어)가 스레드 단위로 실행하게 된다. 즉, CPU에 의해 실행되는 것은 프로세스가 아닌 스레드다.

프로세스의 역할

프로세스는 스레드가 실행될 수 있는 환경을 제공하는 컨테이너 역할을 수행한다. 여기엔 메모리 공간, 시스템 자원(네트워크 연결) 등이 포함되어 있다. 스레드는 프로세스가 제공하는 여러 자원을 활용하게 된다. 스레드라는 것이 프로세스의 자원을 활용하는 독립적인 존재로 볼 수 있다. 하지만 이들은 제약없이 활동할 수 없으며, CPU를 일종의 에너지원으로 삼아 움직일 수 있다.

멀티 스레드 환경의 프로그래밍을 이해하고 분석할 때, 각각의 스레드가 코드를 병렬적으로 수행함을 확인할 수 있다. 하지만 각 스레드가 그러한 작업을 수행할 수 있는 것은 실질적으로 여러 CPU가 각 스레드를 가져가 안에 있는 코드를 실행하기 때문이다. 이러한 개념을 확실히 잡아둬야 이후 멀티 스레드 개념을 다룰 때 혼동하지 않을 것이다.

참고 자료

  1. 인프런 김영한 자바 고급 1편

'CS > 운영체제' 카테고리의 다른 글

컨텍스트 스위칭  (0) 2024.08.17
멀티 태스킹과 멀티 프로세싱  (0) 2024.08.12
주기억장치 관리  (0) 2022.04.26
프로세스(Process) 관리  (0) 2022.04.26
운영체제(Operating System)란  (0) 2022.04.25