Shared memory Interprocessor Communication
process들이 통신하기 원하는 메모리를 공유하는 영역
이 통신은 OS가 아닌 user의 프로세스의 관할로 이루어진다.
이 메커니즘의 주된 문제점은 Shared memory에 접근할때, user의 프로세스가 동기화 될것인가가 문제이다. (이에 대한 문제는 이후에 다룰것이다.)
Shared Data Code / Producer Process#define BUFFER_SIZE 10 typedef struct { ... } item; item buffer[BUFFER_SIZE]; int in = 0; // 새로운 아이템을 넣을 위치 int out = 0; // 지금 사용하고 있는 아이템 위치
위와 같은 솔루션으로 실행될 경우 BUFFER을 모두 채우지 못하고 BUFFER-1 만큼 맊에 사용하지 못한다. 만약 in과 out이 동시에 0을 가르친다면 해당 BUFFER은 empty가 되어 버린다.
Shared Data Code / Circular Producer Processitem next_produced; while(true){ while(((in + 1) % BUFFER_SIZE) == out){ ; } buffer[in] = next_produced; in = (in + 1) % BUFFER_SIZE; }
위와 같은 솔루션은 버퍼가 모두 채워지면 다시 앞으로 가서 버퍼를 채우는 방식이다.
Shared Data Code / Consumer Processitem next_produced; while(true){ while (in == out){ ; } next_consumed = buffer[out]; out = (out+1) %BUFFER_SIZE; }
Consumer Process의 경우 Buffer를 하나씩 채우되 circular 연산으로 버퍼를 소비한다. 다만 in과 out이 동일해지는 경우가 Buffer가 모두 채워지는 경우와 아예 비어있는 경우는 구분 해야하기에 Buffer에서 한자리는 제외하고 사용해야 한다.
그럼 빈공간 없이 BUFFER를 이용하는 방법은 없을까? 생각해보자
Message Passing
이 메커니즘은 프로세스간 **통신(Communication)**과 **동기화(Synchronize)**를 위한 두가지 용도로 쓰인다.
- Send(message)
- recieve(massage)
- 송수신하는 메세지는 고정일수도 있고 가변적 일수도 있다.
그래서 만약 P에서 Q로 Message Passing 방식으로 통신한다면 **Communication Link**를 개설하게 된다. 이때 통신에 있어 고려해야 할것은
- 링크의 설정 방법
- 링크당 허용되는 프로세스의 수
- 통신에 필요한 링크의 수
- 링크 용량
- 메세지 크기
- 양방향 통신 or 단방향 통신
또한 Message Passing의 Communication link를구현에서 주의해야할 점은
- 물리적 제약
- 공유 메모리
- Hardware bus
- 네트워크
- 논리적 제약
- 직접적 / 간접적(Direct/ indirect)
- 동기/비동기
- 버퍼링 방법
Direct Communication
받는 사람의 이름을 명시적으로 표기해서 보내주는 방법
- send(P, message) : P process에게 message를 보내라
- receive(Q, message) : Q Process에게 message를 보내라
받는 사람을 명시적으로 표기해주기 때문에 다음과 같은 특성을 가진다
- Link가 자동적으로 개설된다.
- 받는 사람이 명확하기에 서로 1쌍의 통신선만 맺어주면된다.
- 각 쌍마다 1개의 link만 개설하면 된다.
- link는 일반적으로 쌍방향 통신이 가능하다.
Indirect Communication
간접 통신에 있어서는 Message는 통칭 **Mailbox**, Mach OS에서는 **Port**라고 칭하며 각 메일 박스는 **Uniqu id**를 가진다.
프로세스들은 이러한 상황에서 Mailbox를 공유할때에만 통신할수 있으며 다음과 같은 특징을 가진다.
- Link는 프로세스에 일반 Mail Box를 공유할때에만 개설된다.
- 이 링크는 다수의 프로세스와 연관이 있다
- 각 프로세스 쌍들은 수개의 통신 Link를 공유한다.
- Link는 일방통행이거나 양방향 통신을 수행한다.
간접 통신에서의 동작은 다음과 같다.
- 새로운 Mailbox를 만든다
- Mailbox를 통해 메세지를 주고 받는다.
- Mail box를 삭제한다.
Send(A, message) : Mailbox A에 message를 보낸다
receive(A, message) : Mailbox A에서 message를 받는다.
문제는 하나의 Mailbox에 여러 Process가 접근할때가 문제인데 이때 처리하는 방식은 다음과 같다.
- 들어온 프로세스들이 2개씩 연관지어서 send와 receive를 연관지어준다
- 한번에 한개의 프로세스만 Mailbox에 접근시켜준다.
- 시스템에서 receiver를 임의로 골라서 Sender가 누군지 알려준다.
Message Passing for Synchronization
Message passing 방식에는 **Blocking**방식과 **Non-Blocking**방식이 있다
Blocking 방식은 **Synchronous**한 방식으로 <u>Sender가 상대가 Receive할때까지 Block하는 동안 진행할 수 없도록 막는 방식이고 그 반대도 업무가 맞아 떨어질때까지 일을 중단한다.</u>
한편 Non-Blocking 방식은 **asynchronous**한 방식으로 <u>Blocking 방식에 데이터 손실을 방지하고자 Queue를 사용하여 message를 Send하는 방식</u>으로 대신 Receiver 입장에서는 무효한 NULL Message를 받을수도 있는 방식이다.
만약 그래서 Sender와 Receiver가 둘다 Blocking 방식으로 Message Passing 방식을 구동한다면 이를 **rendezvous**(랑데부)라고 한다. 그리고 맞아 떨어지는 순간을 이용해 <u>Synchronization 효과를 얻을수 있다.</u>
Buffering
그래서 위에서 말했다시피 Queue는 link로 보낼 Message를 담고 있음으로서 Blocking Send와 Blocking Receiver의 성능을 향상 시킨다.
그래서 이를 구현하는 방식에는 3가지가 있는데
- Zero Capacity: Queue가 비어있음 (Rendezvous함)
- Bounded Capacity: 유한한 메세지를 저장하고 Buffer가 가득 찰때까지 기다렸다가 Link로 보냄
- Unbounded Capacity: 무한히 메세지를 저장하고 계속 Sender를 구동 시킴
IPC Sytem Example (POSIX)
POSIX 시스템의 경우 다음과 같은 과정으로 Shared Memory를 시행한다.
- 최초에 Shared Memory Segment에 대한 Process를 open한다.
- shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
- 대상의 크기를 설정한다.
- ftruncate(shm_fd, 4096);
- **mmap()**함수를 이용해 Shared memory를 확보하고 File의 pointer를 받아낸다.
mmap() 함수 분석
mmap( addr, length, port, flags, fd, offset);
addr: 시작주소로 일반적으로 NULL이 들어가면 선택된 페이지를 선택
length: Shared memory의 길이
port: 보호 여부
PORT_EXEC: Mailbox 실행
PORT_READ: Mailbox 읽기
PORT_WRITE: Mailbox 쓰기
PORT_NONE: Mailbox (??????)
flags: 플래그
MAP_SHARED: Memory 공유
MAP_PRIVATE: Memory 복제
copy-on -write: Memory 공유후 수정 시 복제
offset: 시작지점으로 일반적으로 현재의 페이지 단위를 넣음
IPC Sytem Example (Window)
윈도우 시스템에서는 RPC와 유사한 Advance local procedure call(ALPC)를 Message Passing 방식으로 사용함.
- 같은 시스템에 있는 프로세스들에서 사용됨 (Window는 다중운영환경인 Subsystem으로 구성되어 있음)
- 통신 채널을 개설하고 유지하는데 Port를 사용함
Pipe
프로세스 2개가 통신하는 통로
Simplex: 일방향 통신
Half duplex: 한번에 한쪽만 통신
Full duplex: 양방향 동시 통신 가능
Pipe에 대한 Issue
- 쌍방향, 단방향 통신이 될것인가
- 서로 통신하는 프로세스가 서로 Parent-Child 관계 인가?
- 파이프가 네트워크 넘어서도 사용가능한것인가? (일반적으로 Socket으로 사용함)
pipe의 사용 예: ls | less (ls 프로세스와 less 프로세스를 파이프로 연결)
Ordinary Pipe
- 가장 일반적이 표준화된 Pipe으로 Read-end(Consumer 용)와 Wirte-end(Producer용)으로 구분됨
- 일반적으로 양방향으로 통신하게 된다.
- 이 파이프로 통신하기 위해서는 두 프로세스가 서로 Parent-Child관계 이어야함
- 윈도우에서는 이를 **Anonymous pipes**라고 함
int pipe(int fd[2]); fd[0] = read-end; fd[1] = write-end;Name pipes
ordinary pipe에 비해 다른 관계의 process에 연결될 수 있음. => 더욱 파워풀한 면이 있음
단방향성 pipe로 몇몇 Process가 통신을 위해 named pipe로 사용될수 있음
int mkfifo(const char *pathname, mode_t mode); //pathname: FIFO name //mode_t: FIFO's permissionshell에서 Pipe명령어가 실행되는 과정
![Unix Pipes](https://web.cse.ohio-state.edu/~mamrak.1/CIS762/alt_multi_pipe.gif)
위와 같은 경우 ps명령어가 실행되면서 하위에 sort 명령어에 대한 child Process를 그 밑에 less 명령어에 대한 child process를 만들고 실행되면서 상위에 대한 결과물을 하위의 프로세스로 Pipe를 통해 전달한다.
Socket
- 외부 통신을 위한 통로
- 1024번까지는 이미 역할이 정해져 있음
- 소켓은 네트워크 시간에...
Remote Procedure Call
<u> 네트워크를 통한 다른 컴퓨터에 함수나 프로세스를 다루는 기술</u>
네트워크를 통해서 마치 자신의 컴퓨터에 Procedure을 호출하듯이 하는 기술
**Stubs**: 상요자 쪽에서 Proxy를 통해 서버에서 Procedure처럼 작동하게 하는 Proxy
**marshalls**: 내부 데이터를 네트워크를 통해 전송하기 위해 가공하는 과정
**unmarshalls**: 받은 데이터를 네트워크를 받아 복원하는 과정
**MIDL**: Stub 코드를 컴파일 하기 위한 언어
![RPC (remote procedure call) process - Stack Overflow](https://i.stack.imgur.com/nnpg4.jpg)
미래의 나는 RPC 내용을 보충할것 반드시
'공부 학습' 카테고리의 다른 글
시스템프로그래밍 - 함수정리 (0) | 2021.03.24 |
---|---|
운영체제 4주차 -1 (0) | 2021.03.22 |
시스템프로그래밍 2주차 (0) | 2021.03.15 |
운영체제 3주차 - 1 (0) | 2021.03.15 |
시스템 논문 리뷰 1 (0) | 2021.03.15 |