Post

Ch3. Process

Ch3. Process

목표

  • 프로세스의 개별 구성 요소를 식별하고, 그것들이 운영체제에서 어떻게 표현되고 스케줄되는지?
  • 프로세스가 운영체제에서 어떻게 생성되고 종료되는지
  • 프로세스 간 통신 (IPC)을 공유 메모리와 메시지 전달 방식에 대해
  • 파이프와 POSIX 공유 메모리를 이용해 프로세스 간 통신을 수행하는 프로그램
  • 소켁과 원격 프로시저 호출을 사용해 클라이언트-버서 통신을 설명

1. 프로세스란?

실행중인 프로그램이다. -> 프로세스의 실행은 순차적으로 진행되어야 한다. 즉, 디스크에 실행 파일 형태로 저장되어 있는 프로그램이 메모리에 로딩되어 실행되면 프로세스가 된다.

  • 구성요소
    • 프로그램 코드 (Text Section)
    • 현재 수행중인 활동 (PC, processor registers)
    • 임시 데이터를 담는 스택 (Stack)
      • 함수 매개변수, 반환 주소, 지역 변수 등
    • 데이터 섹션 (Data section) : 전역변수들을 포함
    • Heap : 실행중 동적으로 할당되는 메모리 영역

1-1. 프로세스의 상태

  • 생성 : 프로세그가 생성
  • 실행 : 실행중
  • 대기 : 어떤 이벤트가 발생하길 기다리는 중
  • 준비 : 프로세서에 할당되길 기다리는 중
  • 종료 : 실행 종료

1- 2. 프로세스 컨트롤 블럭 (PCB)

각 프로세스의 여러 정보가 담겨있는 블럭
task conrtol block 이라고 하기도함

  • 구성요소
    • Process state - running, waiting, etc
    • Program counter - 다음 실행 명령어의 위치
    • CPU registers - 해당 프로세스에 사용되는 모든 레지스터의 값
    • CPU 스케줄링 정보 - 우선순위, 스케줄링 큐 포인터 등
    • 메모리 관리 정보 - 프로세스에 할당된 메모리 정보
    • Accounting information - 사용한 CPU 시간, 시작 이후 경과 시간, 제한 시간 등
    • 입출력 상태 정보 - 프로세스에 할당된 I/O 장치, 열린 파일 목록 등

2. 프로세스 스케줄링

CPU 사용률를 극대화하고, 프로세스를 CPU 코어에 빠르게 전환시킴
프로세스 스케줄러는 사용 가능한 프로세스 중에서 다음에 CPU에서 실행 할 것을 선택한다.

  • 여러 개의 스케줄링 큐를 유지한다.
    • 준비 큐 : 메인 메모리에 있는, 실행 준비가 된 모든 프로세스의 집합
    • 대기 큐 : 어떤 이벤트를 기다리는 프로세스들의 집합
    • 프로세스는 여러 큐 사이를 이동한다.

2-1. CPU 프로세스간 전환 (Context Switch)

context switch는 CPU가 한 프로세스에서 다른 프로세스로 전환될 때 발생하는 현상을 말

  • CPU가 다른 프로세스로 전환할때, 현재 상태를 PCB에 저장하고, 새 프로세스의 저장된 상태를 불러온다.
  • 프로세스의 컨텍스트는 PCB에 모두 저장된다.
  • 컨텍스트 스위티 시간은 오버헤드이며, 전환중에는 실제 작업을 하지 못한다.
    • 운영체제와 PCB가 복잡할수록 -> 컨텍스트 스위치 시간도 길어짐.
  • 전환 시간은 하드웨어 지원 여부에 따라도 달라진다.
    • 비용 절감을 위해, 어떤 CPU는 모든 레지터를 한 번에 저장/블러오는 단일 명령을 제공함
      • 이 경우, 컨텍스트 스위치는 단지 현재 레지스터 집합의 포인터만 바꾸는 것으로 충분.

3. 프로세스의 생성

부모 프로세스가 자식 프로세스를 만든다. 자식 프로세스도 다른 프로세스 생성 가능 -> 프로세스 트리 형성

  • 프로세스는 고유한 id를 가진다. -> 운영체제가 이걸로 추적하고 관리함
  • 자원 공유 방식 (부모-자식간)
    • 모든 자원 공유
    • 일부만 공유
    • 자원 공유 없음
  • 실행방식
    • 동시 실행 : 부모와 자식이 동시에 실행됨
    • 부모 대기 : 자식 프로세스가 종료될 때까지 부모가 대
  • 주소 공간 (Address Space)
    • 자식 프로세스는 부모의 복제본으로 생성됨
    • 자식 프로세스는 이후에 다른 프로그램을 로딩해서 실행할 수 있음
  • Unix Example
    • fork() : 새로운 프로세스 생성 system call, 환경변수, 열림 파일 fd 등 모두 상속됨
    • exec() : 새 프로그램으로 교체 (덮어쓰기)
    • wait() : 자식중 하나 종료되기를 기다다림

4. 프로세스 종료

  1. 정상 종료
    • 프로세스가 마지막 문장을 실행한 후, exit() 시스템 호출을 통해 운영체제에게 종료를 요청함
  2. 비정상 종료
    • abort() 시스템 호출로 강제 종료할 수 있음.
    • 종료 이유
      • 자식이 할당된 자원을 초과해서 사용하는 경우
      • 자식에게 맡긴 작업이 더 이상 필요 없게 된 경우
      • 부모가 종료될 예정이며, 우녕체제가 자식이 단독으로 계속 실행되는걸 허용하지 않는 경
  3. 어떤 시싀템은 부모가 먼저 죽으면 자식도 자동으로 죽이기한다.
    • OS가 직접 이렇게함
    • 연쇄 종료(Cascading Termination)
    • ios 초기 버전이 이 방식
  4. 정상적인 자식 종료 대기 (wait())
  5. 좀비 프로세스
    • 자식이 먼저 종료됐지만, 부모가 wait 을 호출하지 않음
    • 자식이 죽었지만, 상태 정보가 커널에 남아 있음
  6. 고아 프로세스
    • 부모가 먼저 종료됨, 자식은 아직 살아서 실행중
    • OS가 pid 1 에게 자식의 관리를 넘김

5. 프로세스 상호간 통신

프로세스 상호간 통신은 두가지로 나눌 수 있다.

  • 독립적인 프로세스 (Independent) -> 다른 것과 전혀 상관 없이 작동
  • 협력하는 프로세스 (Cooperating) -> 다른 프로세스와 자원 공유 등 영향을 받음 협력 프로세스는 왜 필요할까?
    1. 정보 공유 (Information sharing)
    2. 계산 속도 향상 (Computation speedup)
    3. 모듈성 (Modularity)
    4. 편리성 (Convenience)

IPC (Interprocess Communication) 를 이용

  • Shared Memory
  • Messaging Passing

5-1. 생산자-소비자 문제

협력 프로세스에서 발생할 수 있는 문제이다. 생산자(프로세스1)는 데이터를 계속해서 만들고, 소비자(프로세스2)는 데이터를 계속해서 소비한다. 이 두 프로세스는 공유 버퍼에서 데이터를 주고 받는다. 여기서 문제는 생산자가 데이터를 씀과 동시에 소비자가 데이터를 읽게 된다 데이터에 문제가 발생한다. -> Race Condition 발생! -> 그래서 동기화 (Synchronization) 이 필수다.

  • Unbounded Buffer (무한 버퍼)
    • 이론상 버퍼 크기에 제한이 없음
    • Producer는 언제든 데이터를 계속 넣을 수 있음
    • 현실적으로는 메모리 한계 때문에 구현이 어려움
  • 🔸 Bounded Buffer (유한 버퍼)
    • 버퍼 크기가 고정됨 (fixed)
    • 버퍼가 꽉 차면 Producer는 기다려야 하고,
    • 버퍼가 비면 Consumer도 기다려야 함

5-2. Shared-Memory

프로세스들끼리 공통으로 사용하는 메모리 영역을 말함

  • 공유 메모리의 사용은 운영체제가 아닌 사용자 프로세스가 직접 관리
  • 즉, 프로세스가 직접 언제, 어떻게 접근할지 스스로 결정해야 함
  • 여러 프로세스가 동시에 메모리를 건드리면 충돌이 발생할 수 있음 -> 동기화가 중요함

5-3. Messaging Passing

프로세스 간에 통신(communicate) 하거나 동시에 동기화(synchronize) 하도록 만드는 방법

  • 프로세스들이 서로 공유 메모리 없이도 통신할 수 있도록 함
  • 모든 통신은 메시지를 주고받는 방식으로 이뤄짐 ✔ 즉, shared variable 없이도 IPC 가능!

5-3-1 Direct Communication

프로세스끼리 메시지를 주고받을 때, 서로의 이름을 명시적으로 알아야 함

1
2
send(P, message)    // P에게 메시지를 보냄  
receive(Q, message) // Q로부터 메시지를 받음
  • 통신이 요청되면 운영체제가 자동으로 링크를 설정함
  • 하나의 링크에는 딱 두 프로세스만 연결됨, 두 프로세스간 하나의 링크만 존재
  • 단방향일 수 있지만, 보통은 양방향

5-3-2 Indirect Communication

프로세스는 서로를 직접 지정하지 않고, mailbox(메일박스) 또는 port(포트)를 통해 메시지를 주고받음

1
2
send(mailbox_id, message)
receive(mailbox_id, message)
  • 메일 박스의 특징
    • 고유한 id를 가짐
    • 공통된 메일박스를 공유한 프로세스끼리만 통신 가능
    • 하나의 링크에 여러 프로세스 연결 가능
    • 프로세스 쌍은 여러개의 메일박스를 공유할 수 있음
    • 링크는 단방향, 양방향 모두 가능
  • 발생 가능한 문제
    • 메일박스에 도착한 내용을 누구 읽을 것인가?
      • 1. 메일박스를 최대 2개 프로세스만 공유하게 제한
      • 2. 한 번에 한 프로세스만 receive 실행 허용
      • 3. 운영체제가 수신자 자동 선택

5-4 Syncronization (동기화)

메시지 전달은 blocking or non-blocking으로 동작할 수 있다.

Blocking

프로세스가 상대가 준비될 때까지 멈추는 방식

  • 보낸 쪽(sender)은 상대가 받을 때까지 멈춤
    • → 상대가 받을 준비가 될 때까지 기다림
  • 받는 쪽(receiver)은 메시지가 도착할 때까지 멈춤
    • → 없으면 기다림

Non-Blocking

프로세스가 상대 상태에 상관없이 그냥 진행하는 방식

  • 메시지를 보내고 바로 다음 코드 실행
    • 만약 받을 준비가 안 되어 있으면 → 메시지 손실 위험 있음
    • 따라서 Queue를 이용하면 손실 없이 처리 가능
  • 받을 준비가 되어 있지 않아도 그냥 실행
    • 결과는:
    • 유효한 메시지 받음 (메시지 도착함)
    • 또는 Null 메시지 (메시지 없음)

5-5 Buffering

메시지를 바로 받지 못할 경우를 대비해서, 통신 링크에 Queue(대기열) 형태로 메시지를 저장해두는 방식

Zero Capacity (용량 0)

  • 버퍼가 없음 → 메시지를 저장할 공간 없음
  • 보내는 쪽은 반드시 받는 쪽이 준비되어 있어야 보낼 수 있음

Bounded Capacity (유한한 용량)

  • 메시지를 저장할 고정된 크기의 큐가 존재 (ex: 최대 10개)
  • 큐가 꽉 차면(sender는 대기) / 큐가 비면(receiver는 대기)
  • 현재 가장 많이 사용하는 방식

Unbounded Capacity (무한한 용량)

  • 큐의 크기가 이론적으로 무한대
  • 아무리 많은 메시지를 보내도 다 저장됨 → sender는 절대 기다리지 않음

6. Pipe (파이프)

파이프는 한 프로세스에서 다른 프로세스로 데이터를 전달하는 통로(conduit)

파이프의 종류

  • Ordinary Pipe
    • 반드시 부모-자식 관계가 필요
    • 파이프를 만든 프로세스 안에서만 사용가능 (외부 사용불가)
  • Named Pipe
    • 서로 관계가 없어도 사용 가능
    • 파이프에 이름이 있으므로 외부에서도 사용가

6-1. Ordinary Pipe

일반적인 파이프는 생산자-소비자 관계로 통신하고 있다 파이프는 한쪽에서 쓰고(생산자), 다른 한쪽에서 읽는다 (소비자) 단방향 형태로 동작한다. (양방향도 가능 - 파이프 두개 이용)

6-2. Named Pipe

이름이 있는 파이프. 파일시스템 상의 특별한 파일로 존재 → 여러 프로세스가 관계 없이 공유 가능

This post is licensed under CC BY 4.0 by the author.