본 벨로그의 내용 및 이미지는 다음의 강의를 참고해서 작성이 되었으며, 틀린 내용이 있을 수도 있으니 너그럽게 봐주시면 감사하겠습니다:)
기본적으로 프로세스와 스레드는 cpu core에서 실행되는 하나의 처리 단위이다. 일반적으로 OS는 프로세스를 하나의 작업(=관리) 단위로 보고, 하나의 프로세스 안에는 개별화된 코드의 흐름이 있을 수 있는데, 그 개별화된 하나의 코드의 흐름을 스레드라고 정의한다. 이때 하나의 프로세스 안에 여러 개의 코드의 흐름이 있는 경우에 멀티스레딩이라고 한다.
그렇다면 프로세스란 무엇인가?
우리가 짜놓은 코드는 프로그램의 형태로 2차메모리인 HDD나 SDD에 저장이 된다. 이 프로그램을 실행하면, OS는 프로세스가 실행되기 위한 제한된 연산장치의 공간을 각 프로세스에 할당하는데 이를 Virtual Memory (가상 메모리)라고 한다. 위의 그림에서 보이는 것처럼 프로세스는 이러한 가상 메모리 공간을 실행 명령을 포함하는 코드들이 포함된 Code영역 Static 변수 혹은 Global 변수가 포함된 Data 영역, 동적 메모리 영역인 Heap 영역, Stack 영역이 차지하며, 해당 프로세스가 어느 정도까지 처리되었는지 확인하기 위해 필요한 Process Control Block (PID, PC, Register, ...) 역시 가상 메모리 공간 위에 올라간다.
서두에 하나의 프로세스 안에 여러개의 스레드가 존재할 수 있다고 했다. 이 말은 곧 하나의 프로세스 안에 있는 여러 개의 스레드의 공간은 OS가 그 프로세스에 할당된 가상 메모리로 그 공간이 한정된다는 뜻이다. 각 스레드들은 가상 메모리 내에서 공용 공간으로 사용할 수 있는 공간도 있지만, 각각의 스레드만이 사용할 수 있는 공간이 Thread Local Storage라는 공간도 존재한다.
다시 프로세스로 돌아와서, CPU는 한번에 하나의 작업만을 처리할 수 밖에 없기 때문에 여러 프로세스들을 동시에 (작은 단위로 나누어서 하나씩) 처리하기 위해서는 하나의 프로세스를 처리하다가 그 프로세스를 대기상태로 보내고, 다시 다른 프로세스를 처리하는 시분할 방식이 도입되었다.
시분할 방식을 위해서는 각 프로세스는 여러 상태로 전이되면서 관리되는데, 프로세스가 가질 수 있는 상태를 구체적으로 명시해보면 다음과 같다.
Context switching은 실행 상태에 있던 프로세스(P1)가 타임아웃이 되면 PCB1에 자신의 상태를 저장하고 준비 상태에 있던 프로세스 P2가 PCB2에 있는 자신의 상태를 가져와서 실행하는 CPU내에서 문맥이 변경되면서 연산이 실행되는 과정을 의미한다.
프로세스의 구조는 위의 그림에서 보이는 것처럼 크게 4가지로 나누어진다.
프로그램이 시작되면 OS 프로그램을 실행하기 위해 프로세스를 생성한다. 다시 말해 OS는 프로세스를 위해 PCB 및 해당 프로세스를 실행하기 위한 공간인 Virtual Memory Space를 할당한다.
SSD로부터 매번 RAM까지 프로그램을 올리려면 시간이 많이 걸리기 때문에 이미 실행 중인 프로세스로부터 새로운 프로세스를 복사하는 방법도 있다. (이미 구글 크롬을 실행하고 있는데 새로운 창을 띄우거나 이미 워드프로그램을 실행 중인데 또 실행) 대표적인 방법으로는 fork()와 exec()이 있다고 한다.
프로세스가 생성되면 CPU 스케줄러는 프로세스가 해야 할 일을 CPU에 전달하고 실제 작업은 CPU가 수행한다. 이때 CPU 스케줄러가 CPU에 전달하는 일 하나가 스레드이다.
그렇다면 스레드를 사용하는 이유는 무엇일까? 프로세스는 크게 프로세스가 실행되면서 바뀌지 않는 영역인 정적인 영역과 작업을 하면서 바뀌는 동적인 영역(레지스터, 힙, 스택)으로 구분된다. 이때 OS가 빠른 작업을 위해 fork()를 통해 프로세스를 여러 개 만들면 multi-tasking을 한다고 할 수 있다. 하지만 multi-tasking은 불필요한 정적 영역을 계속 메모리에 복사하기 때문에 비효율성을 초래한다. 따라서 하나의 VMS안에서 정적인 영역은 공유하고 스레드별로 독립적인 동적 영역을 가지면서 작업을 하는 multi-threading이라는 개념이 도입되었다. Multi-threading에서는 각 스레드 별로 동기화 이슈를 처리하는 것이 중요하다고 한다.
cf) Mutli-processing vs Mulit-threading
멀티프로세싱은 CPU를 여러 개 사용하여 여러 개의 스레드를 동시에 처리하는 작업 환경을 말한다. 하나의 컴퓨커에 여러 개의 CPU 혹은 하나의 CPU 내 여러 개의 코어에 스레드를 배정하여 동시에 작동하는 경우 멀티프로세싱이라고 한다. 반면 멀티스레딩은 '프로세스' 내 작업을 여러 개의 스레드로 분할함으로써 작업의 부담을 줄이는 프로세스 운영 기법이다.
멀티스레드의 장점으로는
멀티스레드의 단점으로는
스레드는 프로세스와 마찬가지로 구현하는 주체에 따라서 '사용자 스레드'와 '커널 스레드'로 나누어 진다.
1 to N Model
하나의 커널 스레드가 여러개의 사용자 스레드와 mapping되는 모델. 사용자 스레드 간의 문맥 교환과 같은 부가 작업이 줄어들어 속도가 빠르다는 장점은 있지만, 하나의 커널 스레드가 여러 사용자 스레드와 연결되어 있기 때문에 커널 스레드가 대기 상태에 들어가면 모든 사용자 스레드가 같이 대기 상태로 들어가게 된다. 또한 멀티코어나 멀티프로세스의 이점을 충분히 이용할 수 없다는 단점도 존재한다.
1 to 1 Model
하나의 사용자 스레드가 하나의 커널 스레드와 mapping된 모델. 커널 스레드가 독립적으로 스케줄링되기 때문에 작업 효율성이 높으며, 사용자 스레드는 커널 스레드가 제공하는 보호 기능과 같은 기능을 사용할 수도 있다. 하지만 (여러 스레드 생성으로 인한) 높은 생성비용 및 문맥 교환할 때의 오버헤드 비용은 단점이다.
M to N Model
M개의 사용자 스레드가 N개의 커널 스레드로 (일반적으로 M>N) mapping되는 모델. 1 to N Model과 1 to 1 Model의 장단점을 모두 가지고 있다.