## 목차 ##



## 1. 프로세스 간 통신 ##

(1) 프로세스 간 통신의 개념

  • 프로세스 간 통신(Inter Process Communication - IPC)

    • 같은 컴퓨터에 있는 다른 프로세스와의 통신
    • 네트워크로 연결된 다른 컴퓨터 프로세스와의 통신
  • 프로세스 내부 통신

    • 프로세스 내 스레드끼리의 통신
    • 전역변수, 파일을 이용하여 데이터 교환
  • 프로세스 간 데이터 통신

    • 같은 컴퓨터의 프로세스 간 통신
    • 공용파일, 운영체제가 제공하는 파이프를 통해 데이터 교환
  • 네트워크 데이터 통신

    • 원격 컴퓨터 프로세스 간 통신
    • 소켓을 통해 데이터 교환
    • ex) RPC(원격 프로시저 호출)



(2) 프로세스 간 통신의 분류

  • 방향에 따른 분류

    • 양방향 통신 : 동시에 양쪽 방향으로 전송 가능. 일반적인 통신 방법이다. ex) 소켓
    • 반양방향 통신 : 양쪽 방향으로 전송할 수 있지만 동시 전송은 불가능. ex) 무전기
    • 단방향 통신 : 한쪽 방향으로만 전송 가능. 프로세스간 통신에서 전역변수와 파이프가 여기에 해당한다.
    • ex) 1개의 전역변수에 두 프로세스가 데이터를 동시에, 혹은 차례로 전송하면 하나는 지워지기때문에 이는 단방향 통신에 해당한다.
  • 통신 구현에 따른 분류

    • 동기화 통신
      • 데이터가 도착했음을 알려주는 기능이 있는 통신
      • ex) 파이프, 소켓
    • 비동기 통신
      • 반복루프 등을 통해 데이터가 도착했는지를 주기적으로 확인하는 바쁜 대기(busy wait) 방식을 사용하는 통신
      • ex) 전역변수, 파일



(3) 프로세스 간 통신의 종류

  • 전역변수

    • 데이터를 보내는 쪽에서 전역변수에 값을 write
    • 데이터를 받는 쪽에서 전역변수의 값을 read
    • 부모 프로세스가 전역변수 선언 후 자식 프로세스를 만들면 통신을 할 수 있다.
    • 쓰기 프로세스가 데이터를 언제 쓸지 알 수 없어 반복루프를 통해 계속 확인해야 한다.(바쁜 대기)
  • 파일

    • open : 파일 기술자(file descriptor) 획득(파일 열기)
    • read/write : 파일 기술자를 통해 파일 입출력
    • close : 파일 기술자 반납(파일 닫기)
    • 이 방식은 부모-자식 관계의 프로세스들 사이에 많이 사용된다.
    • 부모 프로세스가 wait()함수를 사용하여 자식 프로세스를 기다려주는 자체 동기화 방식 사용
  • 파이프

    • 운영체제 동기화 지원
    • 파일과 비슷하게 open() 함수로 기술자 획득
    • close() 함수로 마무리
    • 이름 없는 파이프
      • 일반적인 파이프
      • 부모-자식, 형제 프로세스와 같이 관련 있는 프로세스 간 통신에 사용
    • 이름 있는 파이프
      • FIFO라 불리는 특수 파일을 사용
      • 관련 없는 프로세스 간 통신에 사용
  • 소켓

    • 주로 원격에 있는 프로세스와의 통신에 사용
    • 자신의 소켓과 상대 프로세스의 소켓을 바인딩(binding)
    • 프로세스가 자신의 소켓에 데이터를 쓰면 바인딩 된 프로세스가 소켓을 통해 읽을 수 있다.
    • 운영체제 동기화 지원



## 2. 공유 자원과 임계구역 ##

(1) 공유 자원 접근

  • 2개 이상의 프로세스가 공유 자원을 병행적으로 읽거나 쓰는 상황
    • 경쟁 조건이라고 한다.
    • 공유자원 접근 순서에 따라 실행 결과가 달라질 수 있다.
      race_condition
    • 두 번째 프로세스가 실행한 결과를 첫 번째 프로세스가 다시 덮어쓴다.



(2) 임계구역

  • 임계구역(critical section)
    • 공유자원 접근 순서에 따라 실행 결과가 달라지는 프로그램의 영역
    • 임계 구역에서는 프로세스들이 동시에 작업하면 안된다.
    • 한 프로세스가 임계구역에서 작업 중일때는 다른 프로세스는 기다려야한다.



(3) 생산자-소비자 문제

  • 생산자 프로세스, 소비자 프로세스는 독립적으로 작업
    • 생산자 프로세스는 데이터를 버퍼에 쓰기
    • 소비자 프로세스는 버퍼에서 데이터를 읽기
    • 전역변수 sum은 버퍼에 있는 데이터의 갯수

producer_consumer_problem

  • 현재 sum이 3인 상태에서 생산자가 1개를 추가, 소비자가 1개를 빼가려 하는 상황을 가정해보자.

    • 현재 sum=3 → 생산자 sum=4 계산 → 소비자 sum=2 계산 → 소비자 sum=2 저장 → 생산자 sum=4 저장
    • 위와 같은 순서로 일어나면 실제 데이터는 3개인데 sum이 4가 된다.
  • 하드웨어 자원들은 임계 구역이다.



(4) 임계구역 해결 조건

  • 상호 배제(mutual exclusion)

    • 한 프로세스가 임계구역 내에 있을때 다른 프로세스는 임계구역에 들어갈 수 없다.
  • 한정 대기(bounded waiting)

    • 임계구역을 진입하려는 프로세스가 무한대기하지 않아야한다.
  • 진행의 융통성(progress flexibility)

    • 한 프로세스가 다른 프로세스의 진행을 방해하면 안된다.
    • 임계구역이 비어있으면 프로세스는 항상 임계구역에 진입할 수 있다.



## 3. 임계구역 해결 방법 ##

임계구역 문제를 해결하는 단순한 방법은 잠금(lock)이다. 하나의 프로세스가 임계구역에 진입해있는 동안 빠져나오기 전까지 lock을 걸어 다른 프로세스의 진입을 막는 것이다.

(1) 기본 코드 소개

  • 임계구역 코드 진입 전 lock인지 확인 후 lock이면 대기

  • 임계구역에 진입할 대는 lock을 걸고 임계구역에서 빠져나올때는 lock을 해제한다.

...
while(lock == true); //lock이면 대기
lock = true; // 락
//임계구역
lock = false; // 락 해제
...



(2) 임계구역 해결 조건을 고려한 코드 설계

  • 상호 배제 문제
while(lock == true);
//여기서 프로세스1 타임아웃 -> 프로세스2가 lock == false 확인 후 임계구역 진입 -> 프로세스 2 타임아웃 -> 프로세스 1 임계구역 진입
lock = true;
//임계구역
lock = false;

위 코드는 상호 배제를 충족하지 않는다. 두 프로세스가 동시에 임계구역에 진입할 가능성이 존재한다.


  • 한정 대기 문제

프로세스1 코드

lock1 = true;
while(lock2 == true);
//임계구역
lock1 = false;



프로세스2 코드

lock2 = true;
while(lock1 == false);
//임계구역
lock2 = false;

위 코드는 잠금을 하고 다른 프로세스의 진입을 확인하므로 상호 배제가 보장된다.

만약 프로세스1이 lock1 = true;를 실행하고 타임아웃 된 다음 문맥교환 후 프로세스2가 lock2 = true;를 실행하고 타임아웃 된다면? 이후로는 두 프로세스 모두 while문을 벗어나지 못한다. 따라서 위 코드는 한정대기 문제를 충족하지 못한다. 이러한 상황을 교착상태(deadlock)라고 한다. 즉, 프로세스가 살아있으나 진행되지 못함을 의미한다.


  • 진행의 융통성 문제

프로세스1 코드

while(lock == 2);
//임계구역
lock = 2;



프로세스2 코드

while(lock == 1);
//임계구역
lock = 1;

한 프로세스가 사용후에는 항상 lock을 다른 프로세스의 숫자로 바꾸어놓는다. 따라서 다른 하나의 프로세스가 임계구역 진입 후 lock 값을 바꾸기 전까지는 임계구역에 진입할 수 없다. 항상 번갈아가며 실행될 수밖에 없다. 이러면 임계구역이 사용중이지 않더라도 다른 프로세스가 사용할 때까지 기다려야한다. 따라서 진행의 융통성 문제를 보장하지 못한다.


  • 검사와 지정
    • 하드웨어적으로 여러 명령어가 동시에 실행되도록 하는 기법
    • 명령어를 실행하는 도중에 타임아웃이 걸리지 않도록 하는 방식(원자성 - atomicity)
while(testandset(&lock)==true);
//lock==true이면 대기하다가 false이면 true로 바꾸고 반복문 탈출



(3) 피터슨 알고리즘

프로세스1

lock1 = true;
turn = 2;
while(lock2 == true && turn == 2);
//임계구역
lock1 = false;



프로세스2

lock2 = true;
turn = 1;
while(lock1 == true && turn == 1);
//임계구역
lock2 = false;

두 프로세스 모두 락을 걸었더라도 turn 변수로 다른 프로세스에 차례를 양보하게 된다. turn 변수는 1 혹은 2중 하나만 가질 수 있으므로 두 프로세스 중 1개는 항상 임계구역에 진입할 수 있어 한정 대기 문제를 해결한다.

  • 피터슨 알고리즘은 임계구역 조건 3가지를 모두 충족한다.
    • 프로세스가 추가되면 공유변수를 추가하고 코드를 변경해야한다.
    • 구조가 복잡하여 현재 잘 사용하지 않는다.
    • 반복루프로 바쁜대기를 사용하여 자원을 낭비한다.



(4) 데커 알고리즘

프로세스1

lock1 = true;
while(lock2 == true) {
    if(turn == 2) {
        lock1 = false;
        while(turn == 2);
        lock1 = true;
    }
}
//임계구역
turn = 2;
lock1 = false;



프로세스2

lock2 = true;
while(lock1 == true) {
    if(turn == 1) {
        lock2 = false;
        while(turn == 1);
        lock2 = true;
    }
}
//임계구역
turn = 1;
lock2 = false;
  • 데커 알고리즘은 임계구역 조건 3가지를 모두 만족한다.
    • 프로세스가 추가되면 공유변수를 추가하고 코드를 변경해야한다.
    • 구조가 복잡하여 현재 잘 사용하지 않는다.
    • 반복루프로 바쁜대기를 사용하여 자원을 낭비한다.



(5) 세마포어

  • 피터슨, 데커 알고리즘의 바쁜대기(busy wait) 사용으로 인한 자원의 낭비를 해결

  • 방법이 간단하고 사용이 쉽다.

semaphore(n) {
    RS = n;
}

P() {
    if(RS > 0)
        RS--;
    else
        block();
}
/****
임계구역
*****/

V() {
    RS++;
    wake_up();
}
  • semaphore(n) : RS를 n으로 초기화한다. n은 사용 가능한 자원의 수

  • P 연산 : RS가 0보다 크면 1 감소시키고 임계구역 진입. 0 이하면 자원이 생길때까지 기다린다.

  • V 연산 : RS값 1 증가. 대기중인 프로세스에 wakeup 신호 전송


  • 세마포어 큐

    • 임계구역이 잠금일 때 진입을 대기하는 프로세스들이 저장되어있는 큐
    • wake_up 신호를 받으면 큐의 첫 번째 프로세스가 임계구역 진입
  • 세마포어의 유형

    • count semaphore
      • 사용 가능한 자원의 수 사용
      • 위에서 봤던 코드가 여기에 해당
    • binary semaphore
      • 1개의 프로세스만 진입 가능
      • 사용중이면 0, 사용가능이면 1
      • count semaphore에서 n이 1인 경우에 해당



## 4. 파일, 파이프, 소켓 프로그래밍 ##

(1) 순차 파일

  • 아무리 큰 파일도 데이터는 개념적으로 한 줄이다.

    • ex) Operating\nSystem\nStudy\0
    • 이것을 순차 파일(sequential file)이라 한다.
  • 파일을 open()하면 파일 기술자(file descriptor)를 얻는다.

    • 모든 파일은 open(), read(), write(), close() 구조다.
    • 파일 기술자는 파일 열기 방식(read-only, read-write 등), 파일 접근 권한, 커서 위치 등의 정보를 저장한다.
    • 파일을 open() 후 프로세스를 fork()하면 파일 기술자는 자식 프로세스에 상속되고 이를 공유한다.



(2) 파이프

  • 운영체제 동기화를 지원하는 단방향 통신

    • 보통 파이프라 하면 이름없는 파이프를 지칭
  • 파이프는 부모-자식 프로세스 혹은 같은 부모를 가진 자식 프로세스 간 통신에 사용된다.

  • 파일 기술자를 사용한다.

    • 읽기/쓰기 기술자가 따로 존재한다.(fd[0], fd[1])
  • 파이프는 대기가 있는 통신이다.

    • read(fd[0], buffer, byte)를 실행하면 파이프로 메시지가 들엉로 때까지 대기한다.
    • 파일처럼 부모,자식 프로세스간의 순서를 위해 wait()로 프로세스가 직접 동기화를 할 필요가 없다.



(3) 네트워킹

  • 네트워크로 연결된 원격 컴퓨터의 프로세스간의 통신 방법
    • 파일과 유사하게 open(), read(), write(), close() 구조로 되어있다.
    • 양방향 동기화 통신

socket_networking


  • 클라이언트는 파일, 파이프에 비해 특별히 추가되는 절차가 없다.

  • 서버는 소켓 생성 후 bind()를 통해 포트에 소켓을 등록한다.

    • 포트(port)는 한 IP에서 특정 프로세스와의 통신을 위한 구분 번호이다.
    • 하나의 포트에는 여러 소켓을 등록할 수 있다.
    • 소켓 등록후에는 listen()이 실행되어 클라이언트의 connect() 요청을 기다린다.
    • 클라이언트 connect()요청이 도착하고 accept()되면 소켓 기술자를 생성해 통신을 시작한다.
    • close()를 통해 소켓 기술자를 닫고 listen()으로 돌아간다.

+ Recent posts