본문 바로가기

TIL

[TIL 2024. 03.19] 프로세스와 스레드

프로그램, 프로세스, 스레드
이 단어들을 처음 보면 개념을 혼동할 수도 있다
아래에서 이들에 대해 자세히 알아보자


프로그램 (Program)

프로그램은 컴퓨터에서 실행할 수 있는 파일을 통칭한다

 

단, 아직 파일을 실행하지 않은 상태이기 때문에 정확한 용어는 '정적 프로그램'(Static Program)이며, 이를 줄여서 우리는 프로그램(Program)이라고 부른다

 

다시 말해, 아직 파일이 저장 장치에 있고 메모리에는 올라가 있지 않은 정적인 상태를 말한다

 

어떤 프로그램을 개발하든지 개발자는 프로그래밍 언어(ex. 파이썬, 자바 등)를 이용하여 코드를 작성한다

즉, 프로그램은 간단히 생각하면 그냥 코드 덩어리이다

 

 

프로세스 (Process)

프로세스는 프로그램을 실행시켜 정적인 프로그램을 동적으로 변하게 하여 프로그램이 실행 중인 상태를 말한다

즉, 컴퓨터에서 실행되어 작업 중인 프로그램을 의미하는 것이다

 

기본적으로 모든 프로그램이 실행되기 위해서는 운영체제가 메모리 공간을 할당해줘야 한다

따라서 프로그램을 실행하는 순간에 (실행)파일이 컴퓨터 메모리에 올라가고, 운영체제로부터 시스템 자원(CPU)을 할당 받아서 프로그램 코드를 실행시키게 된다

 

즉, 프로그램 파일이 메모리에 적재되고 CPU자원을 할당받아 프로그램이 실행되고 있는 상태가 곧 '프로세스'이다

다르게 표현하면 '정적인 코드 덩어리'가 마침내 실행된 것으로도 볼 수 있다

 

 

스레드 (Thread)

결론적으로, 스레드는 프로세스의 한계를 해결하기 위해 만들어졌다.

 

과거에는 프로그램을 실행할 때 프로세스 하나만을 사용했다. 따라서 멀티 작업이 불가능했고, 당연히 파일을 다운로드 받으면서 웹서핑 등 다른 작업들을 수행할 수도 없었다. 즉, 파일을 다운 받을 때는 그 실행이 끝나서 다운이 완료될 때까지 기다려야만 했고, 이것이 곧 '프로세스의 한계'였다

 

스레드란 하나의 프로세스 내에서 동시에 진행되는 작업 및 흐름의 단위이다

또 일반적으로는 스레드 수가 많을수록 프로그램 속도는 물론 동시에 처리할 수 있는 작업이 많아지므로 성능이 올라간다.  (단, 스레드가 많을수록 반드시 성능이 올라간다고는 할 수 없다 -> 오버헤드 관련)

 

하나의 프로그램은 일반적으로 하나의 프로세스를 가지며, 하나의 프로세스는 반드시 하나 이상의 스레드를 가져야 한다.  즉, 프로세스를 생성하면 기본적으로 하나의 메인 스레드가 생성된다. 메인 스레드가 삭제되면 당연히 프로세스도 종료된다

 

프로세스가 하나의 스레드만 가질 것인지(싱글 스레드), 하나 이상의 스레드를 가질 것인지(멀티 스레드)를 선택할 수 있지만, 오늘날 많은 OS에서 멀티 프로세스가 지원하긴 하지만, 기본적으로 멀티 스레드로 설계되는 것이 대부분이다

 

멀티 스레드의 예시를 들어보면, 크롬 브라우저를 실행한 경우(1개의 프로세스)에 그 창 내에서 파일을 다운받고, 웹서핑을 하고, 온라인 쇼핑을 하며, 게임을 할 수도 있다. 이를 가능하게 하는 것이 바로 '멀티 스레드'이다

 

멀티 프로세스 vs 멀티 스레드
-> 이해를 위한 예시: 크롬 브라우저를 실행시
-멀티 프로세스: 상단의 새 창들
-멀티 스레드: 하나의 창 내에서 이뤄지는 network작업, i/o 등

 


프로세스: 메모리 구조

 

프로그램이 실행되어 프로세스가 만들어지면 운영체제로부터 다음 4가지의 메모리 영역(Code, Data, Heap, Stack)을 할당받는다. 이 메모리 영역들은 각각 독립적이다

 

▶ 코드 영역 (Text / Code)

: 개발자가 작성한 프로그램 코드들이 컴파일되어 저장되어 있다

(※ 컴파일이란? 프로그래밍 언어로 작성된 코드를 CPU가 해석 가능한 기계어 형태로 전환하는 것)

 

▶ 데이터 영역 (Data)

: 코드가 실행되면서 사용되는 전역변수, Static 변수 및 각종 데이터들이 모여 있다

 

▶ 힙 영역 (Heap)

: 사용자에 의해 메모리 공간이 동적으로 할당되고 해제되는 데이터들을 모아둔다

동적으로 할당되는 데이터의 예시는 생성자, 인스턴스 등이 있다

 

▶ 스택 영역 (Stack)

: 호출된 함수가 종료되면 돌아올 주소 및 데이터(지역변수, 매개변수, 리턴값 등)이 임시로 저장되는 메모리 공간이다.   Stack은 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸한다

또한 Stack 영역의 메모리가 초과하면 stack overflow 에러가 발생한다

 

 

왼편의 그림을 보면, 스택 영역과 힙 영역만 위/아래로 화살표가 표시되어 있음을 확인할 수 있다

 

그 이유가 무엇일까?

 

이는 스택 영역과 힙 영역은 프로세스의 실행 동안에 그 크기가 동적으로 변할 수 있는 메모리 영역이기 때문이다

 

작성된 코드 및 전역변수나 Static 변수를 각기 가지는 코드 영역과 데이터 영역은 프로세스의 실행 중에 그 크기가 바뀔 여지가 없다

 

하지만 스택 영역과 힙 영역은 그 크기가 커지기도 하고, 작아지기도 하므로 화살표를 통해 이들 메모리 영역이 '동적'임을 나타낸 것이다

 

참고로, 프로세스의 메모리 구조는 각각 독립적이므로 기본적으로 프로세스는 다른 프로세스의 메모리에 직접 접근할 수 없다

-> 방법이 아예 없는 것은 아니고, 특별한 방법이 요구된다

ex. IPC(Inter-Process-Communication), 별도의 공유 메모리를 설정

 


 

스레드: 메모리 구조

 

멀티 스레드 하에서 우리가 하나의 프로세스 내에서 동시에 여러 작업을 할 수 있는 근본적인 이유는 스레드가 프로세스의 자원을 공유하면서 프로세스 실행 흐름의 일부가 되기 때문이다

 

즉, 스레드는 프로세스의 4가지 메모리 영역 중에서 Stack을 제외한 Code, Data, Heap에 대해서는 한 프로세스 내의 모든 스레드들이 공유한다. 그리고 스레드는 Stack만 별도로 고유하게 할당받는다

 

그 결과, 각각의 스레드는 별도의 Stack을 가지고 있지만, 서로 다른 스레드들이 공유자원(esp. Heap영역)에 접근해서 데이터를 가져와서 읽고 쓸 수 있게 된다 (-> 동기화 문제 발생)

 

스레드의 메모리 구조

 

Q. "스레드가 고유한 Stack을 할당받는다"의 의미는?

A. 스택 영역이 저장하는 정보는 함수 수행이 완료된 이후에 복귀할 주소값, 호출시 전달된 인자, 함수 내에서 선언 된 변수 등 모두 함수 호출과 관련되어 있다.
-> 따라서 스레드가 독립적인 Stack을 가졌다는 것은 독립적인 함수 호출이 가능하다는 의미이다. 또한 독립적인 함수호출이 가능하다는 것은 독립적인 실행 흐름을 가질 수 있다는 의미이다

cpu의 작업 처리 방식

: 병렬성(Parallelism) vs 동시성(Concurrency)

왼쪽 그림은 동시성이 single-core에서 일어나는 것과 병렬성이 multiple-core에서 일어나는 것을 잘 보여준다

 

싱글 코어에서 발생하는 동시성은 '문맥 교환'(Context Switching)을 통해 2개의 작업이 CPU를 번갈아 가면서 점유하지만, 그 점유의 지속시간이 극히 짧아서 사용자가 느끼기에는 마치 2개의 작업이 동시에 이루어지는 것처럼 느껴지는 것을 말한다

 

멀티 코어에서 발생하는 병렬성은 각 코어마다 작업이 각기 진행되므로, 물리적으로 2개의 작업이 동시에 이뤄지고 있다

 

 

동시성-싱글 코어 / 병렬성 - 멀티 코어

(cf. "병렬성은 동시성의 하위집합이다")

동시성과 병렬성 비교

 

 

 

 

Reference:

https://inpa.tistory.com/

https://sas-study.tistory.com/

'TIL' 카테고리의 다른 글

[TIL 2024. 03. 21] 2차원 리스트: 총정리  (0) 2024.03.21
[TIL 2024. 03. 20] 데이터베이스와 DBMS  (0) 2024.03.20
[TIL 2024. 03. 18] CS(1)  (0) 2024.03.19
[TIL 2024. 03. 15] Tree 자료구조  (0) 2024.03.18
[TIL 2024. 03. 14] DFS/BFS  (0) 2024.03.14