본문 바로가기

별걸다하는 IT/운영체제 OS

[운영체제OS] 프로세스 쓰레드 뭐가 다를까? Thread가 필요한 이유

[운영체제 완전정복 목차]

안녕하세요~~ 운영체제 관련 포스팅은 오랜만이네요! 

 

저번 포스팅에서 프로그램과 프로세스에 대해 알아봤었는데요,

이번 포스팅에서는 프로세스와 쓰레드 차이에 대해 알아보려고 합니다.

 

이전에 프로그램과 프로세스의 차이에 대해 알고 싶으신 분은 아래 링크를 참고해주세요!

프로그램과 프로세스의 차이: jhnyang.tistory.com/6

 

[운영체제]프로세스와 프로그램 차이는? (Process vs Program)

운영체제 목차 A process is a program in execution Program이란? Program과 Process의 차이는 매우 간단한데 이름이 비슷하기도 하고 워낙 많이 쓰니까 헷갈려하시는 분들이 있더라고요. Program은 실행파일입니.

jhnyang.tistory.com

 

프로세스란? 이전에 배웠던거 간단 리뷰!

프로세스와 쓰레드의 차이를 알려면 당연히 먼저 프로세스에 대해 잘 알고 있어야겠죠?

 

프로세스란~

이미 기존의 글들을 쭉 읽어본 분들이라면 충분히 아시겠지만

프로세스는 프로그램 실행파일을 눌렀을 때 실행되는 하나의 인스턴스입니다.

쉽게 말하면 우리 크롬(chrome)같은거 누르면 여러개의 크롬 탭을 만들어서 하나의 탭으로는 유투브를 보고 하나의 탭으로는 블로그를 쓰고 등 여러 작업을 동시에 할 수 있죠??

크롬 실행파일이 하나 있다고 해서 크롬이 하나만 열리는게 아니예요!

여기서 열리는 하나 하나를 프로세스라고 칭할 수 있습니다.

 

PCB란~

우리가 멀티태스킹 즉 멀티프로세싱이 가능한 이유는, 이러한 여러 프로세스들이 짧은 시간 동안 time sharing 번갈아 실행되기 때문에 마치 동시에 실행되는것처럼 느끼는건데요. A라는 프로세스를 실행하다 B라는 프로세스를 불러서 바꿔치기 하려면 어디서부터 이어서 시작해야할지 등 그에 관련된 정보를 저장하고 있어야 합니다. 그게 PCB process control block이라는 것도 설명을 이전에 쭉 했었어요!

 

컨텍스트 스위칭과 프로세스 상태

또 어떤 프로세스를 골라서 실행시키는게 효율적일까~~ 어떤 방식으로 교체가 진행될까~라는 내용으로 프로세스 상태에 대해서도 우리 같이 얘기를 했었죠? :)

 

IPC 통신

그리고 이 프로세스는 서로 독립적 데이터 영역을 갖기 때문에 통신시 동기화 문제가 있어요. 이를 위해 IPC로 프로세스 통신을 한다고 얘기했었어요.

 

제대로 공부하신 분들은 여기까지 술술 읽혀야 한답니다.

이 모든 것은 운영체제 목차에 순서대로 잘 정리되어 있으니 아직 보지 않은 사람들은 한번쯤 꼭 보는 것을 추천드려요!

 

목차 가면 이렇게 잘 정리되어 이쑴!

프로세스만으로는 부족했을까? 쓰레드가 왜 필요할까?

물론 예전에 쓰레드라는 개념이 없이 프로세스만 존재했을 때가 있었습니다.

그런데 프로세스만으로 요구사항을 충족하기 쉽지 않으니까 당연히 쓰레드라는 개념이 생겼겠죠? 

출처: https://www.codeproject.com/Articles/429144/Simple-Instant-Messenger-with-SSL-Encryption-in-Cs

자아 우리 흔히 쉽게 메신저 프로그램을 만든다고 가정해봅시다. 모든지 내가 만든다고 생각해야 체감이 잘되는 법이죠. 

당연히 내가 키보드로 입력한 것을 가지고 화면에 출력해줘야겠죠?? 

그려먼서 동시에 상대방이 입력한 것도 출력해줘야 해요. (내가 입력 안하면 아무도 말 못하는건 말이 안되죠??)

 

자, 먼저 내 키보드 cin해서 (c++의 경우, c의 경우 scanf가 되겠죠? 뭐 암튼,,) 키보드 입력을 기다리겠죠.

그 때 갑자기 사용자 A로부터 메세지 패킷이 네트워크로 도착했다고 가정합시다. 그럼 이 패킷이 도착했음에도 불구하고 우리는 이를 받을 수가 없어요! 왜냐면 나부터 입력을 받기 위해서 cin이 기다리고 있기 때문이죠.

 

이게 왜 불가능하냐, 프로그램은 위에서 아래로 흐르는 단 하나의 실행 path를 가지고 있습니다. main함수 기억하시죠?ㅎㅎ 내가 cin을 완료해야 그 다음 코드로 넘어가지 뭔가를 할 수가 없다는 겁니다!!

이걸 하나의 실행 path라고 합니다. 

fork 함수를 통해 각자의 분기를 타는 프로세스 두 개를 만들 수 있다!

프로세스 하나당 path는 하나, 우리가 만들고자 하는건 path하나로는 소통이 안되니 안되겠다. 결국 최소 path 두 개가 필요해. 오늘날처럼 쓰레드가 없었던 시절에는 이를 해결하기 위해 프로세스 추가로 생성했습니다.

 

사용자가 입력하는 것을 처리하는 실행 path를 만들고,

네트워크로부터 패킷이 도착하는 것을 처리하는 실행 path를 만들고 

최소 이렇게 해줘야 내가 입력해주는 것과 받는 것을 별도로 동시에 운용할 수 있겠죠!

이게 바로 가장 기본적인 프로세스의 개념입니다. 

 

자 그런데 여기에 문제가 존재하게 됩니다. 프로세스는 각각 독립된 자원할당을 갖습니다. 서로 공유하지를 않아요. 각각 정말 별개의 프로그램처럼 서로에게 관련되지 않은 실행패스를 갖게 되는거죠!

이 실행path를 꼬불꼬불한 실로 표기하는데 그림으로 표현하자면 요렇게 표현할 수 있습니다.

그런데 내가 키보드로부터 입력받은 거, 네트워크로부터 입력받은거 두 개다 모두 화면에 출력할 수 있어야 하잖아요,

결국 키보드에서 입력받은 내용을 네트워크프로세스에 보내주던, 네트워크로부터 입력받은 내용을 키보드에 보내주던, 출력만 처리하는 또 다른 제 3자의 프로세스에 둘이 보내주던 결국!!! 중요한건 프로세스들 사이에서 통신이 발생한다는 겁니다. 이걸 shared memory로 구현을 하던 messaging passing으로 구현을 하던 IPC를 통해야 해요 (IPC에 대해서는 저번 포스팅에서 상세히 설명했으니 넘어가겠습니다) 

 

근데 잘 생각해봤더니 이게 프로그램이 커지고 시간이 지날수록 상당히 비효율적이더라 이겁니다.

프로세스라는걸 하나 만든다는건 PCB라는 것도 하나 만들고, 얘를 실행하는 메모리 공간 또한 별도로 만들고, 그 다음에 이 프로세스랑 저 프로세스랑 저저 프로세스랑 IPC 통신해야 하고 프로세스간에 컨텍스트 스위칭하는 것까지.. 결국 오버헤더가 많더라 이겁니다.

 

그러지 말고 어차피 같은 채팅이면 비슷한 개념으로 프로세스 하나에 여러 흐름을 만들고 그냥 자원을 공유하면 안돼?? 우린 그냥 다수의 흐름이 필요할 뿐이지 각각 굳이 자원낭비하게 크게 크게 일을 벌이지말자 이거인거죠.

이렇게 하나의 프로세스에 흐름이 여러개인 형태이면 (오른쪽 그림처럼)

PCB도 하나면 되고(프로세스가 하나니까), 메모리 공간도 하나니까 각 흐름끼리 데이터를 주고 받을 때 커널이 굳이 중간에 껴서 IPC통신 안해도되지 여러모로 이점이 많더라. 프로세스 하위 다수의 흐름을 실행시킬 수 있는 이런 개념을 만들자 라는 아이디어가 70년대 후반에 나왔고 이것이 바로 쓰레드의 정체인겁니다. ㅎㅎ

그래서 실제 멀티쓰레드를 보면, 스택과 레지스터만 독립적으로 가지고 있을 뿐 OS자원이나 코드 데이터, heap 데이터들은 공유하고 있어요.

실제 쓰레드는 우리가 어떻게 쓰고 있는가??

위는 여러분들이 필요성을 이해하기 쉽도록 큼직 큼직한 예시를 작성해드린거고요. 오늘날 쓰레드는 진짜 많이 사용되고 있죠 이게 프로세스였다면 무거워서 대체 어떻게 써! 라고 생각할 것들이 매우 많아요.

 

자 여러분 워드 프로세스에 문서 작성을 해봅시다.

그러면 워드프로세스를 두개를 띄었다. 기본 프로세스가 두개가 띄어진거예요 근데 좀 더 세부적으로 들어가 생각해봅시다. 여러분 키보드 입력한거 기다리죠?? 그리고 주기적으로 저장해요 (우리 중간에 뻑나서 꺼져도 자동 저장 되어있는 경우 많죠?) 그럼과 동시에 여러분들이 타이핑한거 에러체크까지 해줘요 근데 이런게 만약 하나의 프로세스가지고 실행이 되겠어요?! 안되죠! 물론 저런거 하는 프로세스를 하나하나 다 만들수도 있어요. 그런데 이제 앞의 설명을 들었다면 비효율적임을 알 수 있죠 요새는 이런걸 thread를 생성하는 방식으로 처리를 합니다. 

 

일단 무엇보다 자바의 가상머신은 그 가상머신 그 자체가 하나의 프로세스입니다.

그래서 자바는 프로그램 내에서 실행 path를 여러 개 만드려면 쓰레드를 여러개 만드는 수밖에 없어요. ㅎㅎ

 

출처: https://kinsta.com/blog/err_connection_timed_out/

In certain sitiuatiions, a single application may be required to perform several similar tasks.

For example, a web server accepts client resquests for web pages, images, sound, and so forth. A busy web server may have several (perhaps thousands of) clients concurrently accessing it. 

 

특정 상황에서는 하나의 어플리케이션이 비슷한 여러 작업들을 수행하게 되는데요,

한 예로 웹서버 같은 경우는 웹페이지나 이미지나 소리 등 여러 가지에 대한 클라이언트 요청을 받죠 (뒤로가기라던 링크타고 들어가는 페이지라던가, 웹 페이지 로딩이라던가, 소리라던가 등등)

그런데 어떤 웹서버는 클라이언트 수천명이 동시에 접속할 수 있어요. 그런데 이게 만약 single-threaded process였으면 한 번에 하나의 클라이언트 처리만 가능하니까 많은 사람들이 화면 보자고 긴 시간을 기다려야 하는 상황이 발생했겠죠.

 

이제 우리 실생활에 실제로 실행 path가 하나인 경우는 거의 없다는 것을 느낄 수 있을거예요.

이 덕분에 우리가 여러 작업을 동시에 할 수 있기도 한거랍니다. 

 

왜 쓰레드는 실이라는 이름이 붙었을까?

사진출처: https://softwareengineering.stackexchange.com/questions/225371/why-are-threads-called-threads#:~:text=tl%3Bdr%3A%20They're,its%20attention%20on%20your%20thread.

쓰레드를 만든 사람이 처음 책에다 쓰레드를 꼬불꼬불 실 하나로 그림을 그리고 thread라고 붙였기 때문에 쓰레드가 된 거죠 ㅎㅎ 간단명료한 이유! 왜 그렇게 붙였나에 대해서는, 프로세스와 비교하기 위한 비유적 표현이라고 합니다. 멀티프로세스는 각각 독립적인데 실은 그림처럼 저렇게 엉켜서 (서로 독립적이지 않고 얽혀있다) 결과를 도출한다는 그런거... 결국 프로세스와 쓰레드의 가장 큰 차이는, 자원을 공유하느냐 아니면 독립적이냐 차이로부터 도출되니까요.

 

어려운 말로 쓰레드 정리.  

-제어의 흐름을 의미하는 것으로 프로세스에서 실행의 개념만을 분리한 개념이다.

-프로세스의 구성을 크게 제어의 흐름 부분(실행 단위)과 실행 환경 부분으로 나눌 때, 스레드는 프로세스의 실행 부분을 담당함으로써 실행의 기본 단위가 된다.

from 정보보안기사

프로세스(PROCESS)와 쓰레드(THREAD) 차이/비교 정리

여기까지 읽으셨어면 아래표는 별다른 설명이 없어도 쏙쏙 이해되실거라 믿어요! 상대적인 것임을 기억하시오!

 

프로세스 (PROCESS) 쓰레드 (THREAD)
프로세스들은 헤비한 연산들이다.  쓰레드는 가벼운 연산들이다 
각 프로세스들은 각 고유의 메모리 공간을 가진다  쓰레드는 그들이 속한 프로세스의 자원을 공유한다.
IPC(inter process communication) 통신은 각 프로세스들이 다른 메모리 주소를 가진만큼 느리다.  쓰레드간 통신은 IPC보다 빠르다. 왜냐면 쓰레드는 프로세스에서 메모리를 공유하기 때문!
컨텍스트 스위칭 (문맥교환)은 오버헤드가 크다. (비싸다) 프로세스 내의 쓰레드간 교체는 오버헤드가 덜하다.
프로세스들끼리는 메모리를 공유하지 않는다. 쓰레드는 같은 프로세스에 있는 한 쓰레드끼리 메모리를 공유한다.

 

오늘은 이야기하듯이 개념에 대해서 간단히 이야기 해봤는데, 앞으로는 좀 더 자세히 들여다보도록 해요. 

오늘또한 방문 감사드립니다. 공감/댓글/광고 등은 정보공유하는데 큰 동기가 됩니다. 다음 포스팅에서 또 봐요.