본문 바로가기
CS/Operating System

[Operating System Concepts] Chapter3 Process (Part.2)

by 개복취 2023. 10. 29.

갓룡

  1. IPC
  2. Shared Memory : Producer-Consumer Problem
  3. Message-Passing System
  4. IPC System w/ Producer-Consumer Problem
  5. Pipes
  6. Socket & RPC

IPC (Interprocess Communication)

  • 프로세스는 두가지 방법으로 concurrently 하게 발생할 수 있음
    1. 독립적인 프로세스 → 별 문제없음
    2. cooperating 프로세스 → 서로 영향을 주거나 받는다. 서로 메세지를 주고 받을 때의 문제를 어떻게 할것인가?
       IPC : Interprocess Communication 이용한다.

shared memory, message passing

  • shared memory, message passing 두가지 방법의 통신이 있다. 
    • shared memory : 중간에 메모리를 공유해서 서로 통신하는 방법
    • message passing : 운영체제에 맡겨놓는 방법

 

Shared Memory : Producer-Consumer Problem

  • 생산자 - 소비자 문제 : 한쪽은 생산 한쪽은 소비하는 과정을 의미한다.
    ex) Compiler 에서의 asm코드생성 - assembler소비의 관계, Webserver에서의 HTML file생성 - browser의 소비의 관계
  • 대부분은 한정된 버퍼(bounded buffer)이고, 버퍼를 shared memory로 만들면 된다.
  • shared memory는 메모리의 영역을 의미한다. producer-consumer이 공유하는 영역이다.
  • 서로의 메모리 영역을 침범하지 않는 것이 좋다. 따라서, 공유하는 메모리 영역을 만드는 것이다.
    ex) shm_open(name, O_CREAT | ORDWR, 0666) 으로 공유 메모리 영역을 만든다 (세마포어에서 사용)

shared memory / shm_open

  • producer : shared-memory 에서의 buffer을 채운다
  • consumer : concurrent 하게 돌릴 때 버퍼를 통해 동기화가 잘 이뤄지는지 확인한다.

 

Message-Passing System

  • shared memory 구현하는데 있어서 어렵고 복잡한 경우가 많다.
    • 여러 프로세스가 동시에 메모리에 접근하는 문제가 발생할 수 있어서 별도의 동기화 과정이 필요하다 (추후 서술)
  • 커뮤니케이션 할 때 메세지 패싱 API 를 활용한 OS 에게 책임을 전가하자
    • send(message) / receive(message)를 사용해서 통신하기
  • 여러가지 방법을 통한 통신이 가능하다.
    • Direct Communication (직접 통신)
      • 직접통신하는 경우 : 명시적으로 수령인과 보내는 사람의 이름을 정해야 한다.
      • 커뮤니케이션 링크가 자동적으로 생성된다. (exactly one link)
    • Indirect Communication (간접 통신)
      • 두개의 프로세스가 shared box 가 있을 때, pair 간의 링크가 형성된다.
      • 이 링크는 여러개의 프로세스와 연결시킬 수 있다.
      • 여러개의 링크가 존재할 때, 링크를 어디다 보낼 지 정할 수 있다.
      • create, send, receive, delete의 기능들을 O/S가 알아서 해줌
      • shared box(mail box) 는 내가 정함 → port 정해주기 (localhost : 8080…)

sync / async communication (https://serverlessland.com/event-driven-architecture/visuals/sync-vs-async)

  • Synchronous / Asynchronous Communication (동기화 / 비동기화 통신) 
    • blocking은 synchronous : 전송하고 다 받을 때 까지 대기한다.
    • non-blocking은 asynchronous : 전송하면 자기 일 해도 되므로 효율적이다.

 

IPC System w/ Producer-Consumer Problem

  • fopen과 같은 경우는 hdd에서 공간을 차지한다.
  • 마찬가지로, 공유메모리는 메모리 - 맵(mmap) 되어있는 곳에서 메모리를 생성한다.

 

  • Shared Memory : POSIX Shared Memory
    • POSIX : Portable OS Interface (for UniX)
      1. 공유 메모리 영역을 생성한다.
      2. 바이트 사이즈를 정한다.
      3. 메모리 매핑되어있는 형식을 가지고 온다.

 

Producer : 포인터를 옮겨가면서 Shared memory 영역에다가 써놓는 과정을 한다.

// create shared memory obj
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);

// config the size of the shared memory
ftruncate(shm_fd, 4096);

// map the shared memory obj
ptr = (char *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);

// write to the shared memory
sprintf(ptr, "%s", message)
ptr += strlen("message")

 

Consumer : 포인터를 옮겨가면서 읽어오고, 공유메모리에 적혀있는걸 삭제한다.

shm_fd = shm_open(name, O_RDONLY, 0666);

ptr = (char *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);

// read from shared memory obj
printf("%s", (char *)ptr);

// remove the shared memory
shm_unlink(name);
  • 한번 실행하면 출력되고 그다음 포인터로 옮겨가기 때문에 segfault 발생됨

Pipes

  • Message Passing : Pipes
    • UNIX 환경 아래에서 IPC 통신의 가장 초기버전부터 있었던 매커니즘이다.
    • 파이프는 두개의 프로세스가 서로 통신할 수 있도록 도관의 역할을 해준다.
  • 파이프를 구현하기 전 4가지의 사안에 대해 먼저 고민해봐야 한다.
    1. 양쪽의 방향을 지원하지 않고, 일방향으로만 소통을하는가?
    2. half -duplex , full-duplex : 아싸리 한곳으로 보낼것인가, 또는 동시에 서로 보낼것인가?
    3. 파이프는 구현의 편의상 parent-child 관계를 가져야 할 것이다.
    4. 네트워크에서도 파이프를 사용할 수 있는가? (대신, 소켓을 사용한다.)

typical image of ordinary pipe

  • 두 가지 종류의 pipe가 있다. 둘다 FIFO 방식으로 구성되어 있다.
    • Ordinary pipe : 두개의 프로세스가 서로 (생산자-소비자 관계를 가지고 있으며 주로, parent-child 관계) 통신을 하기 위한 용도 명백하게 프로세스가 어디로부터 왔는지 알 때 사용되는 경우이다. 부모 pid가 동일한 경우에만 사용 가능하다.
    • Named Pipe : 이름을 정해줄 수 있는 파이프 (parent-child 관계가 아니더라도 접근 가능함) 주로, 송 수신할 프로세스가 명확하게 알 때 사용된다. 읽기 쓰기가 동시에 불가하기 때문에 pipe 하나는 읽기전용, 다른 하나는 쓰기 전용으로 사용한다.
  • 양방향 통신이 가능하도록 두개의 파이프를 만든다.
    • parent → child, child → parent
    • 부모가 파이프 쓰기 종단(fd[1]) 에서 데이터를 쓰면 파이프의 읽기 종단(fd[0]) 에서 자식이 읽을 수 있다.

Socket & RPC

  • client-server 시스템에서 두가지의 통신 방식이 사용된다.
  • 포크를 하는 순간 parent, child process가 concurrent하게 돈다.
  • pipe(fd)를 통해 두개의 fd가 생성되었고 parent가 한곳에 write하면 child가 read 해 올 수 있다.

소켓통신과 IPC는 별반 다를게 없다. 아래의 특징을 통해 알아보자

  • 어떻게하면 한 컴퓨터를 특정할 수 있을까? → ip address
  • 파이프는 어떻게 특정시킬까? → port
  • 연결된 파이프와 포트를 하나로 묶으면..? → 소켓
  • problem : 리틀 엔디안 , 빅 엔디안이 서로 통신할 때 문제가 생김.. → RPC 등장

Socket : ip 주소가 있는 파이프

 

  • socket 은 통신의 극점을 의미한다., 각 소켓은 ip 주소와 포트번호 두가지를 접합해서 구별한다.
  • 특정 서비스를 구현하는 서버는 well-known port로 부터 메세지를 기다린다. ssh : 22, FTP : 21, HTTP: 80 … 1024 미만의 포트는 모두 웰논 포트이다
  • 자바가 소켓통신에 대해 매우 쉬운 인터페이스를 제공한다. (multicastSocket : 특정한 곳에 던져주기)

 

RPC : 원격에 있는 함수를 호출하기

  • 자바에서는 RPC를 RMI로 구현했다.
  • 기업에서는 분산처리를 위해 rpc를 사용한다.
  • 원격에 있는 함수를 가져오기 위해 rpc를 사용한다.
  • client side에 있는 stub을 사용하고 객체 직렬화해서 보내주어야 하는데 데이터를 정렬해서 보내주는 것을 'marshall' 라고 한다.
  • server-side 에서의 stub 에서는 메세지를 수신하고 marshall 인자들을 언팩한다.