프로세스와 스레드

HunkiKim·2022년 8월 23일
0

프로세스

프로세스의 개념

먼저 프로세스프로그램의 차이가 있다.

프로그램은 어떤 작업을 할 지 절차를 적어놓은 것이다. 즉 실행하나 그런 개념이 아니라 코드와 같은 개념이다. 이를 실행하면 프로세스가 된다.

프로세스는 컴퓨터 시스템의 작업 단위로 태스크(task)라고도 부른다. 프로세스는 프로그램을 실행을 시킬 때 OS가 PCB(Process Control Block)을 받으면 프로그램에서 프로세스로 전환이 된다. 위에서 말했듯이 실행중인 프로그램을 의미하며 각각의 프로세스는 독립된 메모리 공간을 할당받는다. 이 할당받은 메모리는 위의 PCB가 다룬다.

아래는 시작하기 전 몇가지 용어 정리이다.

CPU는 명령어를 실행하는 연산 장치이다.

메인 메모리 프로세스가 CPU에서 실행되기 위해 대기하는 곳을 말한다. 우리가 흔히 메모리라고 부르는 메모리이다.

I/O Input/Output의 약자이며 파일을 읽고 쓰거나 네트워크 어딘가와 데이터를 주고받거나 입출력 장치와 데이터를 주고받는 것을 말한다.

PCB의 정보 대표적인 세 가지

용어의미
'프로세스 구분자'메모리에는 여러 개의 프로세스가 존재하기 때문에 구분하는 구분자(ID)가 필요하다. 이를 위해 Process IDentification(PID)가 있다.
'메모리 관련 정보'CPU는 실행하려는 프로세스가 메모리 어디에 있는지 알아야 작업이 가능하다. 이를 위해 PCB에는 메모리 위치 정보가 담겨 있다. 또한 메모리 보호를 위한 경계 레지스터(Boundary Register)와 한계 레지스터(Limit Register)도 포함되어 있다.
'각종 중간값'시분할 시스템에서 프로세스가 시간 단위로 여러번 번갈아 가며 실행되는데 이 때 중간에 프로세스를 넘기면 프로세스가 실행중에 넘기는 것이 된다. 이 때 어디까지 실행됐는지를 기록해두고 다시 CPU를 할당 받았을 때 실행하는 위치가 중간값이다.

경계 레지스터(Boundary Register)란 OS영역과 사용자 영역으로 나뉠 때 사용자 영역에 존재하는 프로그램이 운영체제 영역을 침범하지 못하도록 하는 역할을 한다.

한계 레지스터(Limit Register)란 각각의 사용자 프로그램이 기준 주소(Base Address)와 해당 프로그램의 영역 크기를 갖게하여 다른 프로그램의 영역을 침범하지 못하도록 하는 역할을 한다.

프로세스를 실행시키려면 이러한 값들을 관리해야 하며, 이러한 정보를 보관하는 데이터 구조가 PCB이다.

프로세스 제어 블록은 OS가 프로세스를 위해 관리하는 데이터 구조이기 때문에 운영체제 영역에 만들어 진다. 프로세스 종료 시 프로세스가 메모리에서 삭제되고 PCB도 같이 폐기된다.

정리하자면 프로그램이 프로세스가 되는 것은 OS로 부터 PCB를 얻는다는 뜻이고, 프로세스가 종료된다는 것은 PCB가 폐기 된다는 것이다.

Process = Program + PCB

프로세스의 구조

프로세스는 Code,Data,Stack 영역으로 구성된다. Data 영역은 일반 데이터 영역과 Heap 영역으로 나뉜다.

예를들어 프로그램을 실행하면 프로그램은 Code Area에 탑재되고, 콘텐츠는 Data Area, 그리고 이 프로그램을 작동하기 위한 부가 데이터는 Stack Area에서 관리하게 된다.

Code Area

Code Area는 프로그램의 본문이 기술된 곳으로 텍스트 영역(Text Area) 라고도 한다. 또한 코드영역에 탑재된 코드는 읽기 전용이다. 읽기전용이 아니면 중간에 프로그램이 수정되기 때문이다.

Data Area

코드가 실행되면서 사용하는 변수나 파일 등의 각종 데이터를 모아놓은 곳이다. int a=1;과 같은 것이다. 상수로 선언된 변수는 읽기 전용이지만 대부분 변수는 읽기/쓰기 모두 가능하다. Heap은 동적데이터로 구분되는데 이는 뒤에서 자세하게 이야기 할 것이다.

Stack Area

OS가 프로세스를 실행하기 위해 부수적으로 필요한 데이터를 모아놓은 곳이다. 예를 들어 프로세스 내에서 함수를 호출하면 되돌아갈 위치가 필요한데 이와 같은 것을 저장해둔다. 스택 영역은 OS가 사용자의 프로세스를 작동하기 위해 유지하는 영역이므로 사용자는 볼 수 없다. (숨김 영역)

fork()

프로세스가 fork() 시스템 호출을 사용하면 실행 중인 프로세스로부터 새로운 프로세스를 복사한다. 커널에서 제공하는 함수이며 일종의 System Call이다.구글의 Ctrl + N 과 같은 기능이다. 복사를 하면 내용은 똑같지만 PID가 바뀐다.

장점

  • 프로세스 생성 속도가 빠르다.
  • 추가 작업 없이 자원을 상속할 수 있다.
  • 시스템 관리를 효율적으로 할 수 있다.

부모 프로세스는 보통 자식 프로세스가 끝날 때까지 기다려야 한다. 하지만 부모가 먼저 종료되거나 자식이 비정상적으로 종료되어 부모에게 연락을 못할 수 있다. 이러면 자식 프로세스가 종료되지 않거나, 자원이 그대로 남게 된다. 이를 고아 프로세스(orphan process) or 좀비 프로세스(zombie proess)라고 한다. 보통 컴퓨터를 오래 켜두면 느려지는데 이는 저러한 자원이 계속 늘어나기 때문이다.

exec()

exec()는 기존의 프로세스를 새로운 프로세스로 전환하는 함수이다. 이를 fork()와 같이 사용하면 큰 장점이 있다. fork()로 하나의 프로세스를 복사하고 이 프로세스를 exec() 하면 새로운 프로세스로 전환된다. 이러면 새로운 코드 영역만 가져오면 되기 때문에 OS의 작업이 수월하다.

프로세스의 동적 할당 영역

프로세스에는 정적과 동적이 있다고 설명했다. 처음에 코드,데이터,스택 영역이 있다고 했는데 추가적으로 힙 영역이 있다. 코드 영역은 프로그램의 본체, 데이터 영역은 프로그램이 정의한 변수와 데이터가 있는 곳이다. 포인터가 아니라면 변수 선언시 크기가 결정된다. 따라서 코드 영역, 데이터 영역은 프로세스 실행 전에 크기가 결정되고 변하지 않으므로 정적 할당 영역이라고 한다.

스택 영역과 힙 영역은 프로세스가 실행되는 동안 만ㄴ들어지는 영역으로, 크기가 변하는 동적 할당 영역이다.

스택 영역

  1. 함수 호출과 복귀 시에 매개변수의 전달과 실행 순서 및 위치를 위해 사용된다.
  2. 스택은 변수 사용 범위에 영향을 미치는 영역을 구현할 때 사용한다. 프로그램 내의 모든 함수에서 사용이 가능한데 지역변수는 함수를 호출할 때만 사용되고 함수가 끝날때 반환해 줘야한다. 이 때 지역변수를 스택을 사용하여 저장한다.

힙 영역

필요할 때 메모리를 할당 받고 다 쓰고 반환해주는 형식으로 메모리 할당이 유동적이다. 대표적인 예로는 malloc() 이 있으며 자바에서는 어레이리스트와같이 유동적인 리스트에서 사용된다. 이로써 효율적인 메모리 관리가 가능하다.

스레드

스레드의 개념

먼저 앞에서 보았던 프로세스의 작업 과정을 다시 살펴보면, OS가 코드와 데이터를 메모리에 가져오고, PCB를 생성하고, 작업에 필요한 메모리 영역을 확보 후, 준비된 프로세스를 준비 큐에 삽입한다. 프로세스가 생성되면 CPU 스케쥴러는 프로세스가 해야 할 일을 CPU에 전달하고 실제 작업은 CPU가 수행한다. 이때 CPU스케쥴러가 CPU에 전달하는 일 하나가 스레드이다. CPU가 처리하는 작업의 단위는 프로세스로부터 전달받은 스레드이다. 다시 말하면 CPU가 처리하는 작업의 단위는 프로세스로부터 전달받은 스레드이다. OS 입장에서 작업 단위는 프로세스이고 CPU 입장에서의 작업 단위는 스레드이다.

한마디로 프로세스의 코드에 정의된 절차에 따라 CPU에 작업 요청을 하는 실행 단위이다.

여러 개의 스레드가 모여 프로세스를 이루고 여러 개의 프로세스가 모여 처리가 되며, 여러 개의 프로세스를 모아 한꺼번에 처리하는 방법을 일괄 작업(batch job)라고 한다.

프로세스와 스레드의 차이

프로세스와 스레드는 서로서로 미치는 영향이 다르다. 프로세스는 느슨한 연결이 되어있는 반면 스레드는 강한 연결로 되어있다.

예를들어 워드와 스풀러(프린터)는 서로 독립적으로 작동하다가 필요할 때 데이터를 주고받는 형식이다. 서로 어떤 한 프로세스를 종료해도 영향을 미치지 않기 때문에 독립적이다. 이렇게 서로 독립적인 프로세스가 데이터를 주고받을 때는 프로세스간 통신(Inter Process Communication), IPC를 이용한다.

반대로 스레드들은 강하게 연결되어 있어 만약 워드가 종료되면 그안에서 동시에 작업을 하는 스레드들은 다 같이 강제로 종료하게 된다.

단일 프로세스

한 번에 하나의 프로그램만 실행된다. 다른프로그램을 실행하려면 현재 프로그램을 끄고 다시 실행해야 한다. 이 때문에 만약 P1이 실행하다가 I/O작업을 만나면 P1을 멈춘다. 그리고 다시 P1이 실행되다가 다시 I/O.. 이런식으로 하는 방식이다. 실행중에 I/O작업을 만나면 CPU가 아무것도 하지 않게 된다. 따라서 CPU사용률이 좋지 않다.

멀티 프로그래밍

위에서와 달리 여러 개의 프로그램을 메모리에 올려놓고 동시에 실행시키기 위해 나왔다. 위와 달리 I/O 작업이 발생하면 다른 프로그램이 그사이에 CPU에서 실행된다. 즉 CPU가 최대한 쉬지않고 작업을 할 수 있도록 한 프로그램가 실행중이여도 다른 프로세스를 실행시킬 수 있게 된 것이다. 이는 CPU를 극대화 시켜주지면 CPU사용이 길어지면 다른 프로세스는 계속 대기하게 된다.

멀티 태스킹

위에서 한 프로세스가 실행중일때 다른 프로세스가 계속 대기하게 되는 단점을 극복하기 위해 나온 방식이다. 프로세스의 응답 시간을 최소화 시키는데 목적을 둔 방식이다. 멀티태스킹은 운영체제가 CPU에 작업을 줄 때 시간을 잘게 나누어 배분하는 기법이다. 이를 시분할 시스템이라고 하며 이는 나중에 자세하게 다룰 예정이다.

하지만 멀티 태스킹도 결국 하나의 프로세스가 동시에 여러 작업을 수행하지는 못한다는 단점이 있다. 프로세스의 컨텍스트 스위칭은 무거운 작업이며 프로세스 끼리 데이터 공유가 까다롭기 때문이다. CPU가 여러 코어로 등장하게 되었고 스레드가 등장하게 되었다.

멀티 프로세스

사실 프로세스 부분에서 설명을 다 하였지만 간단하게 설명하면 하나의 프로그램을 여러개의 프로세스가 병렬적으로 작업을 수행하는 방식이다. 메모리 침범이나 그러한 것들은 PCB가 처리를 하며 자식 프로세스가 문제가 발생하여도 위에서 설명했듯이 독립된 영역을 사용하기 때문에, 즉 독립적이기 때문에 해당 프로세스만 종료하게 된다. 하지만 독립된 메모리 영역을 사용하기 때문에 메모리를 너무 많이 잡아먹으며 프로세스간 통신(IPC)가 없다면 프로세스끼리의 데이터를 주고받을 수 없다.

멀티 스레드

멀티스레드는 종류가 다양하고 깊게 알아야 한다고 생각한다. 간단하게 설명하면프로세스 내 작업을 여러 개의 스레드로 분할함으로써 작업의 부담을 줄이는 프로세스 운영 기법이다.

멀티스레드의 구조

위에선 fork나 exit를 사용하여 여러 개의 작업을 동시에 처리 했지만 이는 코드영역과 데이터영역이 같은 작업을 메모리에 추가로 할당하여 처리하기 때문에 낭비가 발생한다. 이를 효율적으로 하는 방법은 2개의 프로세스가 아닌 코드, 데이터 등을 공유하고 여러 개의 일을 하나의 프로세스 내에서 하는 것이다. 프로세스는 크게 정적,동적인 영역으로 구분된다. 정적인 영역은 프로세스가 실행되고 바뀌지 않는 영역이고, 동적인 영역은 스레드가 작업을 하면서 값이 바뀌거나 새로 만들어지거나 사라지는 영역이다. 동적인 영역의 대표적인 예는 레지스터 값, 스택 ,힙 등이다.

스택영역에 할당된 각각의 스레드마다 스레드를 위한 포인터들이 있고 Code영역엔 각각의 스레드가 실행될 PC(Program Counter)가 존재한다.

멀티스레드 vs 멀티프로세싱

멀티 스레드는 프로세스 안에 듀얼-스레드 이상이 존재하여 작업을 수행하는 것이고 멀티 프로세싱은 두 개 이상의 코어가 병렬적으로 동시에 수행이 가능함을 말한다.

장점

자원의 중복 사용을 피함으로써 낭비를 막을 수 있다. 또한 하나의 프로세스에서 여러 스레드 사용 시 작업의 효율을 높일 수 있다.

예를 들면 유튜브에서 화면 출력과 동시에 구글 DB로 부터 영상을 네트워크를 통해 받아와야한다. 만약 멀티쓰레드 없이 단일 쓰레드로 이러한 방식을 사용하면 데이터를 다 받을 때 까지 화면을 볼 수 없다. 하지만 멀티 쓰레드로 화면을 보는 동시에 데이터를 받는게 가능해져 끊김없이 쭉 볼 수 있다.

요약하자면

1. 한 스레드가 입출력으로 짝업이 진행되지 않아도 다른 스레드가 작업을 계속해서 사용자가 요구한 것에 대해 응답을 빨리 할 수 있다.
2. 프로세스가 가진 자원을 모든 스레드가 공유해 작업속도가 빨라진다. 또한 메모리부분에서 효율적이다.
3. 자원의 중복을 막았기 때문에 시스템 효율이 증가한다.
4. 2개 이상의 CPU를 가진 컴퓨터에서 멀티스레드 사용 시 다중 CPU(멀티코어)가 멀티스레드를 동시에 처리하여 CPU 사용량은 증가하지만 프로세스의 처리시간이 보다 빨라진다. 즉 시분할이 아닌 진전행 병렬 수행이 가능해진다.

단점

하지만 단점은 존재한다. 결국 한 프로세스 내에서 모든 자원을 공유한다는 것은 프로세스 내에서 문제가 발생하면 모든 스레드에서 문제가 발생하게 된다.

컨텍스트 스위칭

멀티스레드와 멀티프로세스에 대해 알아보았다. 그러면 이런 프로세스/스레드가 다른 프로세스/스레드로 교체되는것도 공부해보자.

앞에서 말한 다른 프로세스/스레드로 교체되는 것을 컨텍스트 스위칭이라고 한다.

오늘날의 컴퓨터는 기본적으로 하나의 Process는 하나 이상의 Thread를 가지며 프로세스에서 다른 프로세스로 바뀐다는 말은 서로 다른 Process에 소속된 Thread가 바뀐다고 생각하면 된다.

Context는 프로세스/스레드의 상태를 말하며 상태는 CPU, 메모리 등등의 상태를 말한다. CPU는 기본적으로 PC,stack pointer 등 register가 있다.

컨텍스트 스위칭은 여러 프로세스/스레드를 동시에 실행시키기 위해 등장했다. 보통 주어진 time slice(quantum)을 다 사용하거나 I/O작업을 해야하거나 다른 리소스를 기다릴 때 등 컨텍스트 스위칭이 발생하게 된다.

컨텍스트 스위칭은 보통 OS 커널에 의해 실행된다. OS 커널은 각종 리소스를 관리하며 감독하는 역할을 한다.

컨텍스트 스위칭은 다른 프로세스끼리 스위칭인지 같은 프로세스의 스레드들끼리 스위칭인지에 따라 다르게 일어난다. 다른 프로세스끼리 스위칭을 process context switching, 같은 프로세스 스위칭은 thread context switching이라고 한다.

공통점
1. 커널 모드에서 실행한다.
2. CPU의 레지스터 상태를 교체한다. 레지스터엔 여러 값들이 존재하는데 P1 실행 도중 P2가 실행되면 P1의 레지스터값을 저장하고 P2가 실행된다.

차이점
1. 프로세스 컨텍스트 스위칭은 가상 메모리 주소 관련 처리를 추가로 수행하게 된다. 따라서 MMU(Memory Manage Unit)도 새로운 주소체계를 바라볼 수 있도록 수정하고 TLB라고 불리는 가상 메모리 주소와 실제 메모리 주소의 매핑정보를 들고있는 캐시도 비워줘야 한다.

이때문에 스레드 컨텍스트 스위칭이 메모리 주소 관련 처리를 하지 않고 같은 메모리 주소를 공유해서 CPU의 상태만 바꿔주면 되기 때문에 더 빠르다.

간접적인 영향
CPU안에 기본적으로 Cache가 있다. Cache는 메모리에서 데이터를 주고 받는데 자주 쓸 것 같은 것은 Cache에 올려 놓는다.

문제는 컨텍스트 스위칭이 일어나면 서로다른 데이터를 캐시에 올리기 때문에 스위칭 직후에 캐시에 가도 이전 정보만 들고있기 때문에 캐시에 원하는 데이터가 없을 확률이 크다. 그나마 같은 프로세스에 속한 스레드 끼리의 컨텍스트 스위칭의 경우엔 같은 메모리 영역을 공유하기 때문에 찾는 데이터가 있을 확률이 크지만 아닐경우 메모리 영역을 공유하지 않기 때문에 존재하지 않는다.

따라서 이는 성능적으로 좋지 않다. 이뉸 유저 관점에서 순수한 오버헤드이다. 즉 간접적인 영향으로 CPU를 잡아먹는다는 의미이다.

0개의 댓글