Search
📙

그로킹 동시성 [CH 5] - 프로세스 간 통신

AI custom autofill
Published
2025/05/11
Category
Programming
Tags
BookReview

5.1 다양한 통신 방식

운영체제에는 스레드 간의 정보 교환을 위한 통신 수단을 프로세스 간 통신(Inter-Process Communication, IPC)이라고 한다.
실질적인 통신은 스레드 간에 일어난다. 프로세스와 스레드를 구분하는 것은 혼란을 일으키기 쉽기 때문에 실행 단위의 작업(task)이라는 용어 사용
가장 널리 쓰이는 IPC
공유 메모리(shared memory)
메시지 전달(message passing)

5.1.1 공유 메모리 IPC

작업간의 정보 교환을 하는 가장 간단한 방법은 공유 메모리를 이용하는 것인데, 가상 주소 공간을 공유하는 두 개 이상의 작업이 메모리를 통해 마치 지역 변수를 다루듯 정보 교환을 하는 방식이다.
어느 한 프로세스 또는 스레드가 메모리의 내용을 변경하면 운영체제를 거치지 않고도 다른 프로세스 또는 스레드에 변경된 내용이 그대로 반영된다.
장점
속도가 가장 빠르며, 자원을 가장 덜 사용한다.
공유 메모리를 할당할 때에는 운영체제의 개입이 필요하지만, 작업끼리 정보를 교환할 때에는 필요하지 않다.
단점
안전한 정보 교환이 어렵다.
같은 프로그램을 실행 중인 두 개 이상의 작업이 같은 데이터 객체를 동시에 읽거나 변경 가능
수평 확장이 어렵다.
규모가 큰 데이터를 처리하는 대규모 분산 시스템에서 사용할 수 없다.
SMP(Symmetric Multiprocessing, 대칭형 다중 처리; 여러 개의 CPU 또는 코어가 하나의 메모리 공간과 OS를 공유하며 동등하게 작업을 처리하는 구조) 방식의 시스템에서는 아주 적합하다. (ex. 일반적인 멀티코어 컴퓨터)
애초에 스레드 자체가 공유 메모리를 염두에 두고 만들어졌다.
공통 시스템 버스에서 병목이 발생해 프로세서를 늘리는 데 한계가 있다.

5.1.2 메시지 전달 IPC

오늘날 가장 널리 쓰이는 IPC 방식
모든 작업에 고유 식별자를 부여하고 이 식별자를 향해 메세지를 주고 받는 식으로 정보를 교환
운영체제는 여기에 쓰일 통신 채널을 수립하고 시스템 콜을 거쳐 작업끼리 메시지를 주고 받는 기능 제공
장점
분산 시스템으로 확장이 쉽다.
단점
아무리 간단하더라도 작업 간에 정보를 교환하려면, 시스템 콜을 경유해 운영체제의 채널로 복사하고, 이를 다시 대상 작업의 사용자 공간으로 복사하는 복잡한 과정을 거쳐야 함.

파이프

가장 간단한 형태의 IPC이며, 동기적으로 작업 간에 정보를 쉽게 전송하지만 양방향 데이터 교환이 필요하다면 두 파이프를 사용(작업 간의 단방향 데이터 흐름을 정의)해야 한다.
가장 적합한 상황은 데이터를 생성하는 프로그램에서 사용하는 프로그램으로 전달하는 역할
익명 파이프(unnamed pipe)
이름이 존재하지 않는다.
부모-자식 또는 형제 프로세스, 동일 프로세스에 포함된 스레드에 있는 작업끼리만 사용 가능
사용이 끝나면 사라짐
명명 파이프(named pipe) - FIFO(First-In, First-Out)
파일 시스템에 생성된다.
관계없는 모든 프로세스에서 접근하여 사용 가능
직접 삭제할 때 까지 존재

메세지 큐

널리 쓰이는 방식으로 메시지 큐(message queue)가 있다.
운영체제에서는 프로세스의 스케줄링, 라우터에서는 패킷을 처리하기 전 저장하는 버퍼의 목적으로 사용하며, MSA간의 정보 교환 및 비동기 처리에서도 널리 쓰임
선입선출 원칙에 따라 메시지를 전달
명명 파이프와는 달리 여러 작업이 함께 메시지를 주고 받을 수 있다.
시스템 내 작업 간의 결합을 느슨하게 할 수 있는 중요한 수단

유닉스 도메인 소켓(UDS)

가장 간단하고 널리 쓰인다.
시스템 내에서 스레드 간 정보 교환에 쓰이는 유닉스 도메인 소켓
어떤 스레드가 소켓에 정보를 기록하면, 다른 스레드가 소켓에서 정보를 읽는 방식이다.
두 엔드포인트에 해당하는 스레드가 각자 소켓을 가지고 이들 소켓끼리 연결되는 구도다.
스레드 간에 정보를 주고받으려면 한쪽 소켓의 출력 스트림에 정보를 기록하고 다른 소켓의 입력 스트림에서 정보를 읽으면 된다.
개발자가 어떤 정보를 보낼 것인지 미리 선별해야 한다는 부담
일반적으로 변경에 유연하며 별다른 수정 없이 네트워크 소켓으로 확장할 수 있어 여러 대의 컴퓨터로 시스템을 확장하기에 유리

5.2 스레드 풀 패턴

대부분의 동시적 애플리케이션은 다중 스레드를 채용하기 때문에, 많은 프레임워크와 프로그래밍 언어에서 채용되는 패턴이 스레드 풀(thread pool)이다.
프로그램이 시작할 때 상당 시간 활용될 워커 스레드를 정해진 수만큼 만들어서 풀에 담아두는 패턴
어떤 작업을 실행해야 할 때가 되면 이 풀에서 미리 만들어둔 스레드를 가져와 그 작업에 배정
개발자는 매번 스레드를 직접 만들 필요가 없다.
스레드를 매번 생성하고 종료하는 데 필요한 오버헤드를 줄이고, 예기치 않은 작업 실패가 스레드에 미치는 영향도 줄일 수 있다.
스레드 수를 정적으로 둘 것인지, 동적으로 변화시킬 것인지에 따라 여러 종류의 전략이 있다.
스레드 풀 종류
작업을 만들어내는 주 스레드 및 워커 스레드가 필요하다. 스레드끼리 통신을 가능케 하려면 어떻게 해야 할까?
스레드 풀과 스레드 간의 정보 교환은 메시지 큐에 맡기면 된다.
작업 목록이 담긴 메시지 큐 + 풀에 담긴 스레드가 이 메시지 큐에서 작업을 하나씩 꺼내 동시적으로 처리하는 구조

5.3 패스워드 크랙하기: 파트 2

예시가 나와있어서 패스
→ 청크단위로 작업을 나누어 스레드 풀에 있는 워커 스레드들이 작업을 처리
주어진 것이 싱글 코어뿐이더라도 동시성을 포기할 필요는 없다.
동시성이 병렬성을 능가할 수 있는 경우도 존재한다.
다음 장에서 동시성을 다루어 보도록 하자.