프로세스가 다른 프로세스와 데이터를 주고받는 것을 프로세스 간 통신, IPC라고 한다. 프로세스 간 통신(IPC)에는 같은 컴퓨터 내에 있는 프로세스 뿐만 아니라 네트워크로 연결된 다른 컴퓨터에 있는 프로세스와의 통신도 포함된다.
파이프, 소켓, RFC 모두 운영체제가 제공하는 방식이며 프로세스 내부 데이터 통신과 공용 파일은 사용자 직접 구현 통신 방식이다.
파이프란 UNIX 시스템의 가장 오래된 통신 방식으로 반이중 통신이다. 커널영역에 생성되어 파이프를 생성한 프로세스만 디스크립터를 갖게 된다.익명 PIPE와 Named PIPE(FIFO) 두 종류가 있으며 둘 다 반이중 통신이다.
RPC(Remote Procedure call)이란, 위치에 상관없이 개발자는 위치에 상관없이 원하는 함수를 사용할 수 있게 해주는 통신 방법이다.
어떤 동작 방식을 결정할 때는 오버헤드를 고려해야 한다. 예를 들어 같은 컴퓨터에 있는 프로세스끼리도 소켓을 이용하여 통신할 수 있다. IP 주소로 127.0.0.1과 같은 루프백(loop back)주소를 사용하면 된다. 다만 소켓을 사용할 때 전처리 과정이 많기 때문에 다른 프로세스간 통신 방법보다 느리다. 그래서 같은 컴퓨터에 있는 프로세스 간 통신에는 소켓을 거의 사용하지 않는다.
프로세스 간 통신 방식은 단순하다. 데이터의 send or receive로 구분된다. 예를 들어 전역 변수를 이용하여 메시지를 주고 받는다고 해보자.
P1 (send) -> 전역 변수 -> (receive) P2 와 같다.
방식 자체는 단순하지만 내부적으론 복잡하다. 예를 들어 상대의 프로세스를 어떻게 찾을 것인지,데이터의 크기를 얼마로 할지, 데이터의 도착 여부를 어떻게 확인하는지 등의 많은 문제등이 있다.
함수 호출도 데이터를 주고받는다는 의미에서 통신이라고 생각할 수도 있지만, 함수는 하나의 프로세스 내에서 순차적으로 실행되기 때문에 통신이라고 부르지 않는다. 프로세스간 통신은 동시에 실행되는 프로세스끼리 데이터를 주고받는 작업을 의미한다.
통신은 데이터가 전송되는 방향에 따라 양방향 통신(duplex communication), 반양방향 통신(half-duplex communication), 단방향 통신(simplex communication)으로 나뉜다.
양방향으로 데이터를 보내면 한 개는 사라진다. 따라서 전역 변수를 양방향으로 사용하고 싶다면 2개를 사용하자.
전역 변수 통신의 문제는 언제 데이터를 보낼지 모르는 것이다. 따라서 루프문을 통해 수시로 전역 변수에 상황을 확인해야 한다. 이를 바쁜 대기(Busy wating)라고 한다. 바쁜 대기는 자원 낭비가 심하다. 바쁜 대기 문제를 해결하기 위해선 데이터가 도착했음을 알려주는 동기화(Synchronization)를 사용한다. 메신저 알림이 대표적인 예시이다. 동기화를 사용하면 운영체제가 알아서 알려준다.
프로세스 간 통신은 동기화 기능이 있느냐 없느냐에 따라 대기가 있는 통신(blocking communication)과 대기가 없는 통신(non-blocking communication)으로 분류된다. 대기가 있는 통신은 동기화 통신(synchronous communication), 대기가 없는 통신은 비동기화 통신(asynchronous communication)라고도 한다.
여태까지의 내용을 정리하면 다음과 같다.
양방향 통신 : 일반적인 통신
양방향 통신 and 대기가 있는 통신 : 소켓
단방향 통신 and 대기가 없는 통신 : 전역 변수, 파일
단방향 통신 and 대기가 있는 통신 : 파이프
프로세스 간 통신은 데이터를 주거나 받는 동작으로 이루어지며 이는 쓰기 연산과 읽기 연산으로 간소화할 수 있다.
공동으로 관리하는 메모리를 사용하여 데이터를 주고받는 것이다. 데이터를 보내는 쪽에서 전역 변수나 파일에 값을 쓰고, 데이터를 받는 쪽에서는 전역 변수의 값을 읽는다. 이 방식은 주로 직접적으로 관련이 있는 프로세스 간에 사용한다. 예를 들어 부모 프로세스가 선언한 전역 변수를 자식 프로세스와 통신을 하여 사용할 수 있다.
int GV;
int main()
{
int pid;
pid = fork();
.
.
.
}
GV는 부모 프로세스와 자식 프로세스가 공유하는 메모리 영역으로, 읽거나 쓰거나 하는 방식으로 통신한다.
서로 연관이 없는 프로세스 간 통신에도 extern 변수와 같은 전역 변수를 사용 가능하다.
파일 입출력 코드는 크게 세 부분으로 구성되어 있다. 즉 파일을 열고(Open), 쓰기(Write) 또는 읽기(Read) 연산을 하나 후, 파일을 닫는다(Close).
첫 부분인 open()은 일종의 준비 단계이다. open() 함수를 이용하여 사용하고자 하는 파일이 있는지, 또 그 파일이 있다면 쓰기 권한이 있는지 확인한다. 정상적으로 파일을 사용할 수 있다면 fd를 반환하는데 fd는 해당 파일에 접근할 수 있는 일종의 열쇠이다.
int main()
{
int fd;
char buf[5];
fd = open("com.txt", 0_RDWR);
write(fd, "Test", 5);
read(fd, buf, 5);
close(fd);
exit(0);
}
이처럼 어떤 파일에 접근할 수 있는 권한인 fd를 파일 기술자(file descriptor)라고 부른다.
정리하자면 프로세스에서 파읽 읽기 혹은 쓰기 권한을 얻은 뒤(Open) 입출력 프로세스에 write 혹은 read 통신을 하고 저장장치에 적용한다.
프로세스 <-> read,write <-> 입출력 프로세스 - 저장장치
형식으로 되어있다.
파일을 이용한 통신은 부모-자식 관계 프로세스 간 통신에 많이 사용되며 운영체제가 프로세스 동기화를 제공하지 않는다. 그래서 보통 wait함수를 이용하여 작업한다.
파이프는 운영체제가 제공하는 동기화 통신 방식으로, 파일 입출력과 같이 open() 함수로 기술자를 얻고 작업을 한 후 close()로 마무리 한다. 그리고 전역 변수와 마친가지로 단방향 통신이다. 파이프로 양방향 통신을 하려면 2개를 사용해야 한다.
작업 형식은 전역 변수 부분에 파이프를 추가한것 뿐이다. 하지만 동기화가 되어있기 때문에 파이프가 실행을 마칠 때 까지 다른 파이프는 작업을 하지 않는다는 차이가 있다.
여러 컴퓨터에 있는 프로세스간 통신을 네트워킹이라고 한다. 네트워킹 상황에서의 통신은 RPC나 소켓을 이용한다. 프로시저 호출이 한 컴퓨터에 있는 함수를 호출하는 것이라면, RPC는 다른 컴퓨터에 있는 함수를 호출하는 것이다. 자바같은 객체지향 언어에서 다른 컴퓨터에 있는 객체의 메서드를 불러와 사용하는 것은 모두 RPC의 예이다.
일반적으로 RPC의 호출은 소켓을 이용한다. 다른 컴퓨터에 있는 프로세스와 통신을 하려면 그 컴퓨터의 위치를 파악하고, 원격자의 시스템 내 여러 프로세스 중 어떤 프로세스와 통신을 할지도 결정해야 한다. 이때 통신하고자 하는 프로세스는 소켓에 쓰기 연산을 하면 데이터가 전송되고, 읽기 연산을 하면 받게된다.
또한 동기화를 지원도 소켓 하나만으로 양방향 통신이 가능하다.
RPC는 위에서 말했듯이 다른 컴퓨터에 있는 객체의 메서드를 불러와 사용하는 것이다.
핵심개념은 Stub이다. 서버와 클라이언트는 다른 주소공간을 사용하고 있다.따라서 함수 호출에 사용되는 매개변수를 변환하는 작업이 필요하다. 작업을 하지 않으면 메모리 매개변수에 대한 포인터가 다른 데이터를 가리키게 된다. 이 변환 작업을 Stub이라고 한다. 즉 로컬에서 쓰던 변수의 주소를 통해 접근하면 이상하기 때문에 이 주소를 원격의 싱크를 맞춰주는 역할을 stub가 해준다.
Stub는 클라이언트와 서버 각각에 존재한다.
위는 정의처럼 쓰이며 우리가 아는 의미로는 아래와 같다.
하지만 이것만 알아선 안된다. IDL이 뭔지 알아야 한다. IDL이란 Interface Definition Language의 약자이다. IDL은 서로 다른 언어로 구현된 클라이언트와 서버 사이에서 클라이언트로부터 서버에 있는 객체의 오퍼레이션을 원격 호출하기 위해 인터페이스를 기술하는 언어이다. 플랫폼에 제약 없이 사용하려면 IDL을 사용하면 인터페이스를 명시해야 한다.
대표적인 IDL은 Google에 ProtocolBuffer가 있다.
즉 레이어들은 아래와 같다.
종류 | 운영체제 동기화 지원 | open()/close() 사용 |
---|---|---|
전역 변수 | X(busy wait) | X |
파일 | X(wait함수) | O |
파이프 | O | O |
소켓 | O | O |