Process, Thread|CS Study

👨‍💻 Process?

프로세스는 컴퓨터 프로그램의 인스턴스로, 하나 이상의 스레드를 통해 실행된다.

쉽게 이야기해서, 프로그램이 실행되어 돌아가고 있는 상태를 의미한다.

🙋‍♂️ 프로그램과 프로세스의 차이가 뭔데?

프로그램은, 어떤 행동을 하기 위해 실행할 수 있는 파일을 의미한다. 그리고, 프로세스는 이 프로그램의 명령어와 데이터가 메모리에 적재되어 돌아가고 있는 상태를 의미한다.

프로그램은 정적인 상태, 프로세스는 동적인 상태라고 이해하면 편하다.

프로세스는, 실행되며 프로세스가 필요로 하는 정보가 메모리에 저장되고, 고유의 프로세스 제어블록(PCB)를 생성한다.

코드, 데이터, 힙, 스택에 관해서는 아래에서 이야기하도록 하고, PCB에 대해서 간략하게 알아보도록 하자. PCB에는 프로세스의 고유한 정보들이 담겨져 있다.

  • Poitner : 준비, 대기 상태의 큐, 즉 프로세스의 현재 위치를 저장
  • Process State : 프로세스 상태
  • PID : 프로세스 고유 번호
  • Program Counter : 프로세스가 다음에 실행할 명령어의 주소를 가리킴
  • Registers : CPU 레지스터에 있는 정보
  • Memory Limits : 운영체제에서 사용하는 메모리 관리 시스템에 대한 정보
  • List of open files : 프로세스를 위해 열린 파일 목록

기본적으로, 우리는 컴퓨터를 쓸 때 여러 프로세스를 이용한다. 유튜브를 보면서 카톡을 하고, 필요한 정보가 있으면 크롬에서 검색을 하기도 한다. 이렇게 보면, 여러 프로세스가 동시에 실행되는 것처럼 보인다.

그러나, 실제로는 한 프로세스 실행을 위해 CPU를 점유할 때, 다른 프로세스는 실행이 불가능하다.

그럼 어째서 우린 동시에 진행되는 것처럼 보이는걸까? 그것은, 동시 실행을 위해 여러 프로세스를 시분할로 실행하기 때문이다. 그리고 이를 컨텍스트 스위칭(Context Switching)이라고 부른다.

위의 그림과 같이, 프로세스들이 실행과 준비 상태를 번갈아가며 CPU에 접근하고, 이 과정이 매우 빠르게 진행되어 사용하는 우리의 입장에서는 마치 '동시에 일어나는 것'처럼 보여지는 것이다.

컨텍스트 스위칭의 과정은 한 눈에 보기에도 매우 피로해보인다. 매번 캐시를 초기화하고, 메모리 매핑을 초기화하는 작업을 거치므로 잦은 컨텍스트 스위칭은 성능 저하를 불러오기도 한다.

그리고 그 과정에서 나온 것이, 경량화된 프로세스라고 불리우는 스레드이다.


🤷‍♂️ Thread?

어떤 프로세스 내에서 실행되는 흐름의 단위를 의미한다.

우선, 그림에 대해 설명하기 이전에 메모리 영역의 단어들부터 간략하게 알아보도록 하자.

  • Code : 실행 명령 코드, 즉 작성 코드
  • Data : Static, Global과 같은 전역 변수, 정적 변수 저장
    -> 초기화 되지 않은 데이터는 bss에 저장
  • Heap : 동적 메모리 영역
    -> malloc, free, new 등
  • Stack : 지역 변수, 매개 변수, 복귀 번지 등 일시적 데이터
    -> 함수 호출 시 생성, 종료시 반환
🙎‍♂️ 쉿!
stackoverflow 는 stack이 heap 영역을 침범하는 것을 의미한다.

그림을 보면 알겠지만, 코드, 데이터, 힙과 같은 공유 자원은 프로세스 안의 모든 스레드가 가지고 있는 것을 볼 수 있다.

각 스레드는 스택만 독립적으로 보유하고 있고, 이 스택을 통해 독립적인 함수 호출을 함으로서 독립적 실행 흐름을 추가할 수 있다. 이런 특징 때문에, 경량화된 프로세스라고 많이들 이야기하는 것이다.

또, 한 프로세스 안에 여러 스레드가 포함될 수 있고, 이를 멀티 스레딩(Multi-Threading)이라고 이야기한다.


🚶‍♀️ Multi-Process?

다수의 프로세스가 하나 이상의 작업을 동시에 처리하는 것을 의미한다.

단순히 여러 프로그램을 실행하여 여러 프로세스를 돌리는 것을 의미하는게 아니라, 한 프로세스가 여러 일을 동시에 처리할 때 사용하는 처리 방식의 일종을 의미한다.

부모 프로세스에서 자식 프로세스를 생성하여 진행되는데, 부모-자식간의 관계라고 해도 고유의 메모리 영역을 지니게 되고, 프로세스는 서로 IPC 통신을 통해 데이터를 주고받는다.

프로세스가 개별적으로 독립되어 있어 안정성이 높고, 한 프로세스에 문제가 생겨도 다른 프로세스에 영향을 주지 않기 때문에 통째로 정지되는 참사를 방지할 수 있다. 또한, 공유 자원을 사용하지 않기 때문에 동기화 작업을 진행할 필요가 없다.

그러나, 프로세스마다 메모리 공간을 개별적으로 차지하여 메모리 효율이 감소하고, 컨텍스트 스위칭 비용이 증가하며, 공유 자원을 사용하지 않아 프로세스 간 데이터를 주고받을 때 IPC 통신과 같이 복잡한 과정을 거쳐 속도가 느려지게 된다.

한마디로, 안정성은 높지만 속도는 떨어지는 처리 방식이다.


🏃‍♀️ Multi-Thread?

하나의 프로세스를 다수의 실행 단위로 구분하여 자원을 공유하고 자원의 생성과 관리의 중복성을 최소화하여 수행 능력을 향상시키는 것을 의미한다.

하나의 프로세스에서 여러 일을 동시에 수행할 수 있게 해주는 또 다른 처리 방식이다.

기본적으로 공유 자원 중 하나인 Heap 영역을 통해 데이터를 주고 받아 통신 과정이 매우 간단하다. 또한, 프로세스와 달리 개별적인 메모리 공간을 차지할 필요도 없어 메모리 효율이 좋아지고, 컨텍스트 스위칭 비용도 상당히 감소하여 속도 면에서 멀티 프로세스에 비해 굉장히 유리하다.

이렇게만 보면 멀티 스레드가 멀티 프로세스에 비해 굉장히 유리해보이지만, 공유 자원을 사용한다는 것은 양날의 검으로 작용한다.

여러 프로세스에서 하나의 공유 자원에 동시에 접근하면 에러가 발생하고, 이로 인해 동기화 비용이 발생하게 된다. 만약, 에러가 발생해서 프로세스가 종료되는 참사가 발생한다면, 단 하나의 데이터도 보존하지 못한채 그대로 날아가버릴 것이다.

속도와 효율은 뛰어나지만, 안정성을 위해 개발자가 각별히 주의를 기울여야 하는 처리 방식이다.

좋은 웹페이지 즐겨찾기