CPU와 프로세스, 스레드
프로세스란?
프로세스는 간단하게 말해서 ‘현재 작동중인 프로그램’이다. 하드디스크 등의 보조 기억장치에 저장된 데이터, 코드의 집합인 프로그램이 실행되어 메모리에 올라가면 프로세스가 되는 것이다. 프로그램은 메모리에 올라가 프로세스가 되면서 이 프로세스를 처리하기 위한 다양한 정보가 담긴 PCB(Process Control Block)을 생성한다. 이러한 프로세스는 현대의 OS에서 5개의 상태로 나누어 관리한다.
프로세스의 상태
현대의 컴퓨터는 CPU도 멀티 코어를 사용하고 OS의 제어 하에 CPU의 유휴율을 최대한 낮추는 다중 프로그래밍(Multiprogramming)이 사용되므로 프로세스의 상태는 대기, 실행을 넘어 좀 더 복잡한 4가지 상태로 나뉜다.
- 생성(new) : 프로그램이 메모리에 올라가 프로세스가 되기 위한 여러 과정(PCB 생성 등)을 수행하는 상태
- 준비(ready) : CPU를 얻을 때까지 기다리는 상태. CPU의 ready queue에 쌓여 차례를 기다리게 된다.
- 실행(running) : CPU를 얻어 작업을 수행하는 상태. 실행 중인 상태에서도 I/O가 발생하거나 Interrupt가 생기면 CPU를 반납할 수 있다.
- 완료(terminated) : 필요한 작업을 마친 상태. 이 상태에선 더이상 필요없어진 PCB를 폐기하고 메모리에서 프로세스의 데이터를 삭제한다.
- 대기(wait) : CPU를 주어도 사용할 수 없는 상태. 대표적으로 I/O가 발생했을 때 당장 CPU를 주어도 I/O의 완료를 계속 기다려야 하기에 wait 상태로 들어간다.
PCB(Process Control Block)
PCB에는 CPU가 프로세스를 실행할 때 필요한 여러 정보들이 담겨있다.
- 포인터 : 프로세스는 CPU를 얻지 못했을 때 ready queue에 담겨 linked list로 관리된다. 따라서 PCB를 가리키는 포인터가 필요하다.
- 프로세스 상태 : 위에서 배운 5가지 상태의 정보를 담고 있다.
- 프로세스 구분자(PID) : 메모리에 올라온 여러 프로세스들을 서로 구분하기 위한 식별자이다.
- 프로그램 카운터(PC) : 프로그램은 여러 명령어로 이루어져 있다. 프로세스는 CPU를 얻었다 빼앗기는 일이 빈번하므로 어느 명령어까지 실행하였는지를 저장해야 하고 그 역할을 프로그램 카운터가 수행한다.
- 프로세스 우선도 : CPU 스케쥴러의 방식에 따라 프로세스들은 각각 우선도를 가지고 이를 PCB가 저장한다.
- 레지스터 정보 : PC가 가리키는 명령어 전까지 수행했던 작업의 결과를 저장해야 하기에 PCB가 이를 저장한다.
문맥 교환(Context Switch)
문맥 교환(Context Switch)은 현재 CPU를 사용하고 있던 프로세스가 모종의 이유로 나가고 다른 프로세스로 교체되는 것을 말한다. 어디까지나 다른 프로세스로 교체되는 것을 말하기 때문에 Interrupt 등으로 잠시 수행이 멈췄다가 원래의 프로세스로 돌아오는 것은 문맥 교환이라 하지 않는다.
I/O 발생 등의 원인으로 인터럽트가 발생하여 기존 프로세스가 CPU 사용을 중지해야 하는 상황이 왔다고 가정하자. 이 때 기존 프로세스는 지금까지 수행해온 작업의 결과를 PCB의 PC, 레지스터 정보 등에 저장한 뒤 CPU의 사용을 중지한다. 그 후 CPU의 스케줄러에 의해 선택된 다음 프로세스가 들어오고 CPU는 새 프로세스의 PCB에서 다음에 수행해야 할 명령어 등을 알아낸 후 필요한 작업을 수행한다.
스레드(Thread)
스레드(Thread)는 CPU가 실행하는 프로세스의 작업 단위이다. ‘흐름의 단위’라고 표현하기도 한다.
간단한 예시를 하나 들어보자. 예를 들어 우리가 인터넷 브라우저를 키면 프로세스 하나가 실행될 것이다. 그리고 그 인터넷 브라우저에서 파일을 다운받고, 즐겨찾기를 열고, 링크를 클릭하는 등의 여러 작업을 수행하면 각각의 스레드가 프로세스 내에서 작업을 수행할 것이다. 이러한 스레드는 스레드끼리 프로세스에 할당된 코드, 데이터 등을 공유하고 각각의 레지스터와 스택, TCB(Thread Control Block)을 가진다. 프로세스 내의 작은 프로세스라고도 볼 수 있고 실제로 가벼운 프로세스(light process)라고도 부른다. 서로 자원을 공유하는 이 특성이 멀티 프로세스와 멀티 스레드 간의 차이를 만든다.
멀티 프로세스 VS 멀티 스레드
멀티 프로세스(Multi Process)는 하나의 프로그램을 여러 개의 프로세스로 구성하여 각 프로세스가 하나의 작업을 수행하게 하는 것이다. 장점으로는 하나의 프로세스가 잘못되더라도 다른 프로세스가 작동하기 때문에 프로그램은 동작한다는 것이다. 단점은 프로세스 간의 문맥 교환이 빈번하기 때문에 비용이 크다는 것이다.
멀티 스레드(Multi Thread)는 하나의 프로그램을 하나의 프로세스, 여러 개의 스레드로 구성하여 동작하게 하는 것이다. 장점으로는 스레드끼리는 프로세스에 할당된 데이터, 코드 등의 자원을 공유하기 때문에 하나의 스레드를 실행하다가 다른 스레드를 실행하더라도 문맥 교환의 비용이 훨씬 싸기 때문에 속도와 비용 면에서 앞선다는 것이다. 단점으로는 여러 스레드가 자원을 공유하기 때문에 공유하는 자원의 동기화 문제가 발생하고 스레드 하나가 오류가 나면 프로그램 전체가 뻗어버리는 등의 문제가 있다.
스레드 세이프(Thread Safe)
스레드 세이프(Thread Safe)는 여러 스레드가 동시에 작동하더라도 안전하다는 뜻이다. 정확히 표현하자면 여러 스레드가 동시에 실행되어도 각각의 스레드가 그 스레드 하나만을 실행했을 때와 같은 결과를 내야한다는 것이다. 예를 들어 함수가 전역변수를 참조한다면 여러 스레드가 해당 함수를 호출할 때 스레드 세이프하지 않은 결과가 나올 것이다.
지금까지 프로세스와 스레드의 특징, 관계와 차이 등을 알아보았다. 다음 포스팅에서는 이러한 프로세스들을 CPU에서 어떤 순서로 처리할 것인지를 정하는 CPU 스케줄링 방식에 대해 알아보도록 하겠다.