개발자 공부하기/운영체제

[운영체제] IPC, 프로세스 간 통신 방법

스윗 앨리스 2020. 10. 2. 13:28
프로세스 간 통신 (Interprocess Communication, IPC)

컴퓨터 시스템에서 프로그램은 혼자 독자적으로 수행할 수도 있지만 프로그램들 사이에 정보를 교환함으로서 계산 속도를 증가시키거나 편의성을 향상시킬 수 있다.

 

각 프로세스는 자신의 독립적인 메모리 공간을 가지고 다른 프로세스들에 의해 침범당하지 않도록 보호하고 있기 때문에 프로세스 간 통신하기 위해서는 별도의 메커니즘이 필요하다.

 

기본적인 프로세스 개념과 CPU 스케줄링이 막연하게 느껴질때,
아래 포스팅을 보며 다시 복습하자.

[운영체제] 프로세스 개념 정복하기
[운영체제] 프로세스 생성과 종료 / 요약 정리
[운영체제] 프로세스 스케줄링 개념 정리
[운영체제] 프로세스 스케줄링 알고리즘 정리

 

1. 공유 메모리 (shared memory)

커널의 통신 서비스를 이용해 협력하는 프로세스들 사이에 공유되는 메모리 영역(shared memory)을 구축하는 방법이다.

메모리를 직접 접근하기 때문에 속도가 빠르고 사용이 편리하다.

문제점 : 프로세스A가 공유 메모리에 데이터 전달해도 프로세스B가 그것을 알 수 없다 => 별도의 동기화 기술이 필요하다.

 

# 공유메모리를 위한 시스템 API

shared memory 시스템 호출

- shmget() : 동일한 Key를 알고 있는 프로세스들끼리 공유 메모리 생성

- shmat() : 공유 메모리 생성 후 내 프로세스 메모리 공간에 attach한다.

 

=> 내 메모리 공간에 attach 해야한다는 점만 제외하면, dynamic memory allocation 하는 것과 비슷하다.

 

Shared Memory가 어디에 위치하는가

 

<예> 공유 메모리의 생성과 연결
프로세스 A : OS에 공유메모리를 만들어 달라고 요청하면,
실제 RAM에서 일정 부분을 공유 메모리로 떼어주고 이는 별도의 메모리 주소 영역으로 존재하는 것이 아니라
내 프로세스 영역으로 연결이 되게 되어 있다. (프로세스 메모리 상에서 stack과 heap의 중간 영역에 위치)

프로세스 B : 자신의 주소 영역에 공유 메모리를 연결한다.
(A가 공유 메모리를 만들었고, 어떤 Key로 만들었는지는 이미 알고 있는 상태)

 

2. 메세지 패싱 (Message Passing)

커널 메모리 영역에 메시지 전달을 위한 채널을 만들어서 협력하는 프로세스들 사이에 메시지 형태로 정보를 Send/Receive 하는 방법이다. 

커널에서 데이터의 주고 받음을 컨트롤할 수 있어 별도의 동기화 로직이 없어도 된다. 

하지만 커널을 통해서 데이터 주고 받기 때문에 성능 문제가 있을 수 있다.

 

# 메세지 패싱을 위한 시스템 API

 

Message Passing 시스템 호출

- msgget() : 동일한 Key를 알고 있는 프로세스 사이에서 메시지 큐 생성

- msgsnd() : message 전달

- msgrcv() : message 받기

 

Message Passing vc Shared Memory

(a) Message Passing은 커널 영역에 통신을 위한 채널을 만들어 메시지를 send/receive 한다.

(b) 프로세스 간에 동일한 메모리 공간 (Shared Memory)를 바라보고 있다.

 

3. 파이프 (Pipe)

초기 UNIX 시스템의 IPC 기법으로 사실 메시지 전달(Message passing) 방식의 일종이다.

Pipe는 파일 I/O를 통해 프로세스 간 데이터를 주고 받는다. 파이프 생성 시 두개의 파일 디스크립터(read, write)가 return 된다.

 

# 파이프의 종류

- 보통 파이프 (Ordinary Pipe)

저장장치에 실제로 있는 파일이 아니라 커널영역에 존재하는 가상 파일이다.

일반적인 파일 입출력 함수(read/write)를 통해 데이터를 전달하기 때문에 비교적 사용이 간단하다.

부모/자식 프로세스 관계에 있는 경우에만 사용할 수 있고, 통신 방향이 단방향이다.

ex) 부모 -> 자식 or 자식 -> 부모

 

<일반적인 사용법>
부모 프로세스에서 파이프를 만들어두고 fork()를 통해 자식 프로세스를 생성하면 부모 프로세스의 메모리 내용과 PCB가 그대로 복제되고, 커널의 파일 테이블도 그대로 상속되기 때문에 동일 Pipe를 바라보게 된다.

<참고>
exec()를 하는 경우에도 그전에 미리 Pipe를 생성해두었다면 파일 테이블은 그대로 상속된다.)

 

- 지명 파이프 (Named Pipe)

특수한 파일을 이용하여 통신하는 방법이다.

파일 이름만 알면 부모/자식 프로세스 외에도 정보를 공유하는 양방향 통신이 가능해진다.