주제 : Remote Procedure call
"원격"에 있는 "함수 호출"
1. 목적
- 사용 편의성 높여주기, 쉽게 서버의 서비스를 사용하기
- Distributed Transparency : 서버가 있는 줄도 모르게, 로컬 함수호출하듯이 사용하면 투명성 높아짐.
RPC를 직접 개발하려고 할 때 고려사항
- 함수 호출하는 머신과, 함수 실행하는 머신이 다름
- 어떤 함수에 어떤 파라미터를 넣어서 실행해달라고 메시지를 보내야 됨(미들웨어에서 메시지 형식을 만들어줘야됌)
- 파라미터에 값이 아니라 포인터를 넣어야 한다면?
- Persistent : 서버와 클라이언트가 실행중인 상태에서만 사용 가능
예시 : read(fd,buf,nbytes)인 함수를 로컬에서 실행할 경우
- Stack의 필요성
- 함수 호출시 프로그램은 기존 작업을 멈추고 새로운 작업(함수)를 수행해야 함.
- 함수가 끝나고 기존 작업으로 돌아가야 하므로, "복귀 위치", "함수의 로컬데이터"를 저장해둬야 함.
- 이를 위해 스택 사용
- 함수 호출 시 Stack에 저장되는 것
read(fd,buf,nbytes) 호출시 스택에
- fd,buf,nbytes : 함수 인자들
- 복귀 주소 : read가 끝난뒤 돌아갈 메인 프로그램 위치
- read 함수의 지역 변수 :함수 내부에 선언된 임시 데이터
- 함수 호출 흐름 (스택 동작)
- 호출 전
- 메인 프로그램이 실행중이며, 그동안 사용한 지역변수들이 스택에 저장되어 있는 상태
- read(fd,buf,nbytes) 호출
- 함수 인자(fd,buf,nybtes)가 스택에 저장됨.
-메인 프로그램이 read 호출 후 돌아올 복귀 주소가 스택에 저장됨.
-read 내부에서 사용할 지역변수들이 스택에 저장됨.
- read 실행
- 스택에 저장된 데이터를 기반으로 작업 수행
-작업완료 후 돌아감
문제는 여기서 buf는 포인터다. 이걸 다른 기기에 어떻게 파라미터로 넣나? 거기 메모리의 포인터에 뭐가 있을 줄 알고?
call-by-value, call-by-reference, call-by-copy-restore
call-by-reference
- 함수 호출 시, "변수의 메모리 주소"를 전달
- 주소를 참조하여 원래 변수 값을 직접 수정이 됨.
call-by-copy-restore
- 함수 호출시 변수의 값을 복사해서 전달 (call-by-value처럼)
- 함수가 종료되면, "복사된 값이 원래 변수에 복사"
void modify(int x) {
x = 10; // 내부에서 x를 수정
}
int main() {
int a = 5;
modify(a);
// modify가 종료된 후, a가 10으로 복구됨
}
RPC에서는 call-by-copy-store를 사용한다.
주소값을 넣으면 안되고 실제 값을 넣어야 한다.
RPC 동작 흐름

APP은 아무것도 모르고 로컬 함수 실행하듯이 실행한다.
그러면 아래 Stub(미들웨어)가 요청 메시지를 만든다.
그리고 OS로 내려준다.
서버의 OS => stub이 받아서 메시지를 해석하고 함수를 호출하는 것이다.
그리고 함수 실행의 리턴값을 다시 클라이언트로 보내준다.
hetrogeneous RPC : Endian 문제
OS마다 데이터를 다르게 해석할 수 있기 때문에 주의해야 한다.
특히 숫자의 메모리 표현 방식이 다를 수 있는데,
Big-endian vs Little-endian
Endian : 다중 바이트 데이터를 메모리에 저장할 때, 어떤 순서로 배치할 것인가?
Big은 우리가 알듯이 메모리의 낮은 쪽 부터 순서대로
Little은 반대로 저장한다.
이러면 서로 통신할 때 문제가 생길 수 있다.

Ouput Parameter 문제
위에서 read(fd,buf,nbytes)에서 buf는 아웃풋 파라미터다.
함수를 실행한 결과가, 리턴값이 아니라 저 파라미터에 적용이 되서 실행이 된다. 그래서 아웃풋 파라미터다.
위 경우 buf는 클라이언트가 보낼떄는 그냥 짐만 된다. 어차피 데이터도 쓰레기일텐데. 이럴거면 왜 클라가 주냐,
서버가 한번만 보내주면 되는데,
Aysnc RPC (one-way RPC) (안 중요)
RPC를 사용할 때 async한 예제들이 있을 수 있다.
ex. db에 entry 추가 요청, 서비스 시작 요청 등
중요하지 않다.
대신 메시지가 서버에 잘 도착했는지 알 길이 없다.
따라서, 주기적으로 메시지를 보내는 경우에는 쓸만하다.