Process 와 Thread 차이점 정리
프로세스와 쓰레드의 차이점을 정리하려고 한다.
프로세스란
운영체제로부터 할당받은 작업의 단위이다. 안정성을 위해 프로세스마다 자신에게 할당된 메모리 내의 정보에만 접근할 수 있도록 제약을 두었다.
프로세스가 오류가 발생해서 강제 종료가 되었을 때 공유하고 있는 파일을 손상시킨 것이 아니라면 다른 프로세스에는 아무런 영향을 주지 않는다.
프로그램
은 파일이 저장 장치에 저장되어 있지만 메모리에는 올라가 있지 않은 정적인 상태를 말한다.
쓰레드란
프로세스 내에서 실제로 작업을 수행하는 주체를 의미한다. 모든 프로세스에는 한 개 이상의 쓰레드가 존재하며 작업을 수행한다.
쓰레드는 Code/Data/Heap 메모리 영역의 내용을 공유하기 때문에 다른 하나의 쓰레드에서 오류가 발생한다면 같은 프로세스 내의 다른 쓰레드가 모두 강제로 종료가 된다.
멀티가 앞에 붙은 단어에 대해 정리가 필요하다.
멀티프로세스, 멀티쓰레드
멀티프로세스
는 하나의 프로그램을 여러개의 프로세스로 구성하여 각 프로세스가 병렬적으로 작업을 수행하는 것이다.
장점
- 메모리 침범문제를 OS차원에서 해결
- 여러 자식 프로세스 중 하나에 문제가 발생해도 그 프로세스만 종료 됨
단점
- 각 프로세스가 독립된 메모리 영역을 가지고 있기 때문에 작업량이 많아지면서 오버헤드가 발생함(context switching)
- 프로세스 간의 통신이 복잡함(IPC 사용)
멀티쓰레드
는 하나의 응용 프로그램에서 여러 쓰레드를 구성해 각 쓰레드가 하나의 작업을 처리하는 것이다.
장점
- 메모리 공간, 시스템 자원 효율성 증가
- 메모리 영역을 공유하고 있으므로 쓰레드간 통신이 간단함
- context switching시 비용이 적음
단점
- 동기화 문제 발생
- 하나의 쓰레드가 문제가 생기면 전체 프로세스가 영향을 받음
Context Switching
스케줄러가 기존 실행 프로세스를 우선순위 때문에 미루고 새 프로세스로 교체해야 할 때 프로세스 상태 값을 교체하는 작업을 말한다.
흐름설명으로는 운영체제의 스케줄러가 인터럽트를 진행해 더 높은 우선순위를 가진 프로세스가 실행되어야 할 때 스케줄러가 레지스터에 저장된 기준 프로세스 정보 값이나 기존 프로세스 상태 값을 커널 내부에 존재하는 PCB에 저장하고 새 프로세스의 정보 값이나 새 프로세스 상태 값을 PCB에서 다시 가져와 교체하는 작업
프로세스 간의 Context-Switching 은 자원 손실이 많이 발생하는데 쓰레드 간의 Context-Switching에서는 메모리를 공유하고 있는 만큼 부담이 덜 수 있다.
PCB는 Process Metadata들을 저장해 놓는 곳으로 하나의 PCB 안에는 하나의 프로세스의 정보가 담겨있다.
Process Metadata에는 다음과 같이 프로세스 고유 번호(PID), 스케줄링 정보, 프로세스 상태, 레지스터, 프로그램 카운터(다음에 실행되는 명령어 주소) 등이 정보가 있는데 프로세스가 생성되면 PCB에 저장된다.
주의할 점은 Context Switching이 너무 자주 일어나면 오버헤드(사용된 시간과 사용된 메모리의 양) 비용이 발생하여 성능이 떨어진다.
프로세스와 쓰레드 구조 정리
정리
- 쓰레드는 프로세스 안에 포함 되어있다.
- 운영체제가 프로세스에게 Code/Data/Stack/Heap 메모리 영역을 할당해 주고 최소 작업 단위로 인식한다.
- 쓰레드는 프로세스 내에서 Stack 메모리 영역을 제외한 다른 메모리 영역을 같은 프로세스 안에 있는 다른 쓰레드와 공유한다.
- 쓰레드의 스케줄링은 운영체제가 처리하지 않기에 프로그래머가 직접 동기화 문제에 대응할 수 있어야 한다.
쓰레드가 나오면 빠질 수 없는 이야기가 바로 교착 상태(Dead lock)이다.
교착 상태(Dead lock)
두 개 이상의 작업이 서로 상대방의 작업이 끝나기만을 기다리고 있는 것을 교착 상태라고한다.
교착 상태의 조건(4가지)
- 상호배제: 한 리소스는 한 번에 한 프로세스만 사용할 수 있다. (양다리 불가)
- 점유와 대기: 어떤 프로세스가 하나 이상의 리소스를 점유하고 있으면서 다른 프로세스가 가지고 있는 리소스를 기다리고 있다. (욕심부리기)
- 비선점: 프로세스가 테스크를 마친 후 리소스를 자발적으로 반환할 때 가지 기다림(강제 뺏기 불가)
- 환형 대기: 각 프로세스는 순환적으로 다음 프로세스가 요구하는 자원을 가지고 있다. (서로 기다리고 있는 모양)
교착 상태 방지법
- (예방)방지
-
상호 배제 조건을 제거 : 자원을 공유해야 되는데 근본적으로 자원은 공유가 불가능하기 때문에 상호배제 조건을 방지하는 건 불가능하다.
-
점유와 대기 조건 제거 : 필요한 자원을 모두 요청하고 획득해야 한다. 방법 하나는 필요한 모든 자원을 먼저 다 할당해버리고 실행한 뒤 끝나면 다른 시스템 호출에 자원을 할당하는 것, 또 다른 하나는 프로세스가 자원을 전혀 갖고 있지 않을 때만 자원 요청을 허용해 주는 것이다. 단점은 효율성이 좋지 않고 기아 상태 발생 등의 문제점이 있다.
- 비선점 조건 제거 : 어떤 자원을 가진 상태에서 또 다른 자원이 필요하면 가지고 있는 자원을 모두 해제하고 프로세스가 작업을 시작할 때 요청한 새로운 자원과 해제한 자원을 확보하는 방법. 단점은 이미 실행한 작업의 상태를 잃을 수도 있다.
- 환형 대기 : 모든 자원에 고유 할당 번호를 붙이는 것이다. 예로 어떤 프로세스가 R2의 자원을 요청했으면 그다음으론 R3의 자원만 요청할 수 있다.
-
- 회피
교착 상태 예방 측면에서는 효율성과 시스템 처리량을 떨어뜨린다. 교착상태 회피 측면은 자원을 더 효율적으로 사용하려는 것이 목적이다. 리소스 할당에서 교착 상태가 발생할 가능성이 있는 자원 할당을 하지 않는다.
은행원 알고리즘, 자원 할당 그래프가 있다. 알아보기
- 탐지 및 회복
교착 상태가 발생했는지 탐지하고 발생했다면 교착 상태에 빠진 모든 프로세스를 중단시키거나 프로세스를 하나씩 중단 시키면서 탐지 알고리즘으로 교착상태인지 탐지하면서 회복하는 방법이 있다.
그렇다면 쓰레드끼리 메모리를 공유하기때문에 통신이 가능한데 프로세스 끼리는 통신이 불가능할까? 아니다 프로세스간 통신도 가능하다.
프로세스끼리 통신
특정 프로세스가 다른 프로세스에게 영향을 주거나 받지 않으면 독립적인 프로세스, 영향을 주고받으면 협력적인 프로세스라고 한다.
프로세스끼리 통신하기 위해선 IPC(Interprocess communication) 기법이 필요하다. IPC 기법에는 기본적으로 공유 메모리와 메세지 전달의 두 가지 모델이 있다.
대표적인 IPC 통신 방법들
파이프(익명 파이프)
한쪽 방향으로 통신이 가능한 게 파이프의 특징이다. 두 개의 프로세스가 연결되고 하나의 프로세스는 데이터를 쓰기만, 나머지 하나는 데이터를 읽기만 할 수 있다.
양쪽으로 통신을 하기 위해선 두 개의 파이프를 만들어야 가능하다. 읽기와 쓰기 통신을 모두 해야 되는 게 아니라면 파이프는 매우 좋은 방법이 될 수 있다.
익명 파이프는 통신을 할 프로세스가 명확하게 알 수 있는 경우 사용한다. 예를 들어 자식 프로세스와 부모 프로세스 간 통신의 경우에 사용할 수 있다.
Named PIPE(FIFO)
Named PIPE는 전혀 모르는 상태의 프로세스들 사이의 통신의 경우 사용한다. 익명 파이프 단점 중 같은 부모 프로세스를 가지는 프로세스들 사이에서만 통신이 가능하지만 Named PIPE는 그 부분을 해결한 PIPE의 확장이라고 할 수 있다.
부모 프로세스와 무관하게 전혀 다른 모든 프로세스들 사이에는 통신이 가능한데 그 이유는 통신을 위해 이름이 있는 파일을 사용하기 때문이다.
Named PIPE 생성은 mkfifo를 통해 이루어지는데 mkfifo가 성공하면 명명된 파일이 생성된다.
단점은 이 친구도 마찬가지로 읽기 쓰기가 동시에 가능하지 않으며 읽기만 하거나 쓰기만 가능하다. 하지만 통신선로가 파일로 존재하기에 하나를 읽기 전용으로 열고 다른 하나를 쓰기 전용으로 여는 방법으로 이 문제를 해결할 수 있다. 전 이중 통신을 위해서는 두 개의 FIFO 파일이 필요하다.
Message Queue
Queue는 선입선출의 자료구조를 가지는 통신 설비로 커널에서 관리한다. 입출력 방식은 Named PIPE와 동일하다.
다른 점은 Named PIPE가 데이터의 흐름이라면 메시지 큐는 메모리 공간이라는 점이다. 어디에서나 물건을 꺼낼 수 있는 컨테이너 벨트라고 생각하면 된다.
메시지 큐에 쓸 데이터에 번호를 붙임으로써 여러 개의 프로세스가 동시에 데이터를 쉽게 다룰 수 있다.
공유 메모리(Shared Memory)
위에 언급한 것처럼 데이터를 공유하는 방법은 2가지가 있었다.
-
통신을 이용하여 데이터를 주고받기(PIPE, Named PIPE, Message Queue)
-
데이터를 아예 공유하기(Shared Memory)
프로세스 간 메모리 영역을 공유해서 사용할 수 있도록 허용한다. 프로세스가 공유 메모리 할당을 커널에 요청하면 커널은 해당 프로세스에 다른 프로세스들과 공유할 수 있는 특수한 메모리 공간을 할당해 준다. 이후에 어떤 프로세스건 해당 메모리 영역에 접근할 수 있다. 공유 메모리는 중개자가 없어 곧바로 메모리에 접근할 수 있기 때문에 다른 모든 IPC들 중에서 가장 빠르게 작동할 수 있다.
Memory Map
Shared Memory 공간과 마찬가지로 메모리를 공유한다는 측면에 있어서는 서로 비슷한 측면이 있다. 차이점은 Memory Map의 경우 열린 파일을 메모리에 맵핑 시켜서 공유한다는 점이다. 파일은 전역에서 사용할 수 있는 자원이므로 서로 다른 프로세스들끼리 데이터를 공유하는데 문제가 없다는 점을 이용한 방식이다.
Socket
네트워크 소켓 통신을 사용한 데이터 공유로 양쪽 PC에 임의의 포트를 정하고 해당 포트 간의 대화를 통해 주고받는 형식이다.