Post Lists

2019년 2월 15일 금요일

OS Chapter 3 : Process

Part Two Process Management
Process는 그것의 task를 성취하기 위해 실행중인 프로그램으로서 생각되어질 수 있다. 프로세스는 CPU time, memory, files, 그리고 I/O devices 같은 어떤 자원들이 필요할 것이다. 이러한 자원들은 그 프로세스가 생성되거나, 그것이 실행중 둘 중 하나일 때 프로세스에 할당된다.

한 Process는 대부분의 시스템에서 work의 단위이다. 시스템들은 프로세스들의 한 집합으로 구성된다 : OS processes들은 system code를 실행하고, user processes는 user code를 실행한다. 모든 이러한 프로세스들은 병행(concurrently)하여 실행할 것이다.

비록 전통적으로 한 프로세스가 그것이 작동할 때 단일 thread의 제어를 포함했을 지라도, 대부분의 현대 운영체제는 이제 여러 개의 쓰레드들을 가진 프로세스들을 지원한다.

운영체제는 프로세스와 쓰레드 관리의 몇 가지 중요한 측면에 책임이 있다 : 두 사용자와 시스템 프로세스들의 생성과 제거; 프로세스들의 스케듈링; 동기화, 의사소통에 대한 mechanisms의 provision과 프로세스들을 위한 deadlock handling.

여러 프로그램들이 실행되게 하면서, 다양한 프로그램들에 대한 더욱 완고한 통제와 좀 더 많은 구획화를 요구하게 되었고, 이러한 필요성들은 실행중인 프로그램이라는 process의 개념을 만들었다.  process는 현대의 time-sharing system에서 work의 단위이다.


  1. process의 개념 소개 - 실행중인 프로그램, 모든 연산의 기반을 형성하는.
  2. scheduling, 생성, 종료를 포함하는 프로세스들의 여러 특징들을 설명
  3. shared memory와 message passing을 사용하는 프로세스 간의 커뮤니케이션 조사
  4. client-server systems에서의 의사소통 설명
* 프로세스 개념
  • OS를 이야기할 때 발생하는 한 질문은 모든 CPU 활동들을 무엇으로 부를지를 포함한다. batch system은 jobs를 실행하는 반면, time-shared system은 user programs 또는 tasks를 가진다. job과 process라는 용어들은 거의 이 교재에서 거의 혼용하여 사용된다.
  • 한 process는 실행중인 한 프로그래미다. 프로세스는 text section이라고 가끔 알려진 program 코드 이상이다. 그것은 또한 program counter의 값에 나타내어지는 현재 활동과 프로세서 레지스터의 내용들을 포함한다. 한 프로세스는 일반적으로 다음의 process stack을 포함한다.
    • process stack : 함수 파라미터, 반환 주소, local 변수같은 임의의 데이터
    • data section : global 변수를 포함
    • heap : 프로세스 run time동안 동적으로 할당된 메모리
  • 한 프로그램 그 자체로는 한 프로세스가 아니다. 한 프로그램은 disk에 저장된 명령어들의 한 목록을 포함하는 한 파일 같은 (종종 executable file로 불려지는) passive entity이다. 대조적으로, 한 process는 active entity인데, program counter가 실행할 다음의 명령어를 명시하고, 관련된 자원의 집합이 있다. 한 프로그램은 executable file이 메모리에 불러와질 때 한 프로세스가 된다.
  • 한 process가 실행할 때, 그것은 state를 바꾼다. 한 프로세스의 state는 그 프로세스의 현재 활동의 일부로 정의된다. 다음의 상태 중에 하나에 있을 것이다:
    • New : 그 프로세스가 생성 중이다.
    • Running : 명령어가 실행중이다.
    • Waiting : 그 프로세스가 어떤 이벤트가 발생하기를 기다린다 (I/O 완료 또는 신호 수신)
    • Ready : 그 프로세스가 프로세서에 할당되기를 기다린다.
    • Terminatd : 그 프로세스가 실행을 끝냈다.
  • 각 프로세스는 Process Control Block(PCB, 또는 task control block)에 의해 운영체제에서 나타내어진다. PCB는 다음의 것을 포함한다 : 
    • Process state : 그 state는new, ready, running, waiting, halted, 등일지도 모른다.
    • Program counter : 그 counter는 이 프로세스에 대해 실행될 다음 명령어의 주소를 가리킨다.
    • CPU registers : 컴퓨터 아키텍쳐에 따라 그 레지스터들은 개수와 종류에서 다양하다. 그것들은 accumulators, index registers, stack pointers, general-purpose registers 더해서 어떤 condition-code information을 포함한다.
    • CPU-scheduling information : 이 정보는 프로세스 우선순위, 스케쥴링 큐 포인터, 어떤 다른 스케쥴링 파라미터들을 포함한다.
    • Memory-management information : 이 정보는 운영체제에 의해 사용되는 메모리 시스템에 따라 base와 limit registers의 값, page tables, 또는 segment tables같은 항목들을 포함할지도 모른다.
  • 지금까지 이야기한 프로세스 모델은 한 프로세스가 execution의 단일 쓰레드를 수행하는 한 프로그램이라는 것을 암시한다. 그 단일 제어 쓰레드는 그 프로세스가 한 번에 한 task만을 수행하도록 한다. 대부분의 현대 운영체제들은 프로세스 개념을 확장시켰는데, 한 프로세스가 여러개의 실행중인 쓰레드들을 가지고, 한 번에 한 개 이상의 task를 수행하도록 하게 한다. 이 기능은 특히 multicore systems에서 유익하다. 그 시스템에서, 여러 쓰레드들은 병렬로 실행될 수 있다. 쓰레드들을 지원하는 한 시스템에서 PCB는 각 쓰레드에 대한 정보를 포함하도록 팽창된다. 그 시스템 도처에 다른 변화들은 쓰레드들을 지원할 필요가 있다.
* 프로세스 스케쥴링
  • multiprogramming의 목적은 CPU 이용을 극대화하기 위해, 항상 작동중인 어떤 프로세스를 갖게 하는 것이다. time sharing의 목적은 프로세스간의 CPU를 매우 자주 switch해서, 사용자들이 작동하는 각 프로그램과 상호작용할 수 있게 하는 것이다. 이러한 목적들을 충족하기 위해서, 그 process scheduler는 CPU에서 프로그램 실행을 위해 (가급적 몇 가지 이용가능하 프로세스의 한 집합으로부터) 이용가능한 프로세스를 선택한다.
  • 프로세스가 그 시스템에 들어올 때, 그들은 그 시스템에 모든 프로세스들로 구성된 job queue에 들어가진다. main memory에 있고, 실행될 준비가 되어있고 기다리는 프로세스들은 ready queue라고 불려지는 한 list에 유지된다. 이 큐는 일반적으로 linked list로 저장된다. ready-queue header는 그 list에서 첫 번째와 마지막 PCB에 대한 포인터들을 포함한다. 각 PCB는 ready queue에서 다음 PCB를 가리키는 pointer field를 포함한다. 그 시스템은 또한 다른 큐들을 가질 수 있다. 프로세스가 disk같은 shared device에 I/O 요청을 할 때, 그 disk가 바쁘다면 device queue에서 자기 차례를 기다려야 한다. 각 device는 그것 자신의 device queue를 가진다. 한 새로운 프레소스가 ready queue에 넣어진다. 그것은 실행을 위해 선택되거나 또는 보내질 때 까지 기다린다. 그 프로세스가 CPU를 할당받고 실행하기만 한다면, 여러 이벤트들 중 하나가 발생할 수 있다:
    • 프로세스는 I/O request를 발행할 수 있고, I/O queue에 배치된다.
    • 프로세스는 새로운 child process를 만들 수 있고, 그 child의 종료를 기다린다
    • 프로세스는 한 interrupt의 결과로 CPU로부터 강제로 제거될 수 있고, ready queue에서 다시 돌아와질 수 있다.
  • 운영체제는 스케쥴링 목적을 위해 큐들로부터 어떤 방법으로 프로세스들을 선택해야 한다. 그 선택 프로세스는 적절한 스케쥴러에 의해 수행된다. batch system에서, 좀 더 많은 프로세스들이 즉시 실행될 수 있기 보다는 제출된다. 이러한 프로세스들은 mass-storage device(일반적으로 디스크)에 spooled되고, 나중의 실행을위해 유지된다. long-term scheduler 또는 job scheduler는 이 pool로부터 프로세스들을 선택하고 실행을 위해 그것들을 메모리로 불러온다. short-term scheduler 또는 CPU scheduler는 실행할 준비가 된 프로세스들 사이에서 선택하고 그들 중 하나에게 CPU를 할당한다. 
  • 이러한 두 스케쥴러 사이의 주된 차이는 실행 빈번함에 있다. 그 short-term scheduler는 CPU를 위해 새로운 프로세스를 자주 선택해야만 한다. long-term scheduler는 덜 자주 실행된다. long-term scheduler는 the degree of multiprogramming (메모리에 있는 프로세스의 개수)를 제어한다. 만약 멀티프로그래밍의 정도가 안정적이라면, 프로세스 생성의 평균율은 시스템을 떠나는 프로세스의 평균 출발율과 같아야 한다. 따라서, long-term scheduler는 한 프로세스가 시스템을 떠날 때만 불러와질 필요가 있다. 
  • long-term scheduler는 신중한 선택을 해야한다. 대부분의 프로세스들은 I/O bound 또는 CPU bound 둘 중 하나로 설명될 수 있다. I/O bound process는 연산을 하는데 시간을 쓰기 보다 I/O를 하는데 그것의 더 많은 시간을 쓰는 것이다. 대조적으로 CPU-bound process는 연산을 하는데 시간을 써서 I/O 요청을 덜 생ㅅ어한다. long-term scheduler가 I/O bound와 CPU-bound processes들을 좋은 process mix로 선택하는 것이 중요하다. 어떤 시스템에서, long-term scheduler는 없거나 최소로 되어있을지도 모른다. time-sharing systems같은 어떤 운영체제는 부가적인 intermediate level of scheduling을 도입한다. 이 medium-term scheduler의 주된 아이디어는 메모리에서 한 프로세스를 제거하고 (CPU에 대해 active contention으로 부터) 그에 따라 the degree of multiprogramming을 제거하는 것이 가끔씩 이익이 될 수 있다는 것이다. 나중에 그 프로세스는 메모리에 다시 들어올 수 있고, 그것의 실행은 그것이 떠나간 지점에서 계속될 수 있다. 이 전략은 swapping이라고 불려진다. 그 프로세스는 그 medium-term scheduler에 의해 swapped out되고, 나중에 swapped in이 된다. Swapping은 process mix를 개선하는데 필수적일지도 모른다, 메모리 요구사항에서의 변화가 이용가능한 메모리를 지나치게 속박하기 때문이다. 그리고 이것은 메모리가 해제되는 것을 요구한다.
  • interrupts는 운영체제가 CPU를 그것의 현재 task에서 kernel routine으로 바꾸도록 한다. 그러한 연산은 general-purpose systems에서 자주 발생한다. 한 interrupt가 발생할 때, 그 시스템은 CPU에 작동중인 프로세스의 현재 context를 저장할 필요가 있는데, 그것의 프로세싱이 처리되었을 때 그 context를 restore할 수 있게 하고, 필수적으로 그 프로세스를 중지하고 다시 시작하게하기 위해서이다. 그 context는 그 프로세스의 PCB에서 나타내어 진다. 그것은 CPU 레지스터 값, process state, 메모리 관리 정보를 포함한다. generically하게, 그 CPU의 현재 상태에 대해 state save를 수행하고, 그것이 커널 또는 사용자 모드에 있게 하고, 연산을 재개하기 위해 state restore를 한다.
  • CPU를 또 다른 프로세스로 switching하는 것은 현재 프로세스의 state save와 다른 프로세스의 state restore를 수행하는 것을 요구한다. 이 task는 context switch로 알려져있다. 한 context switch가 발생할 때, 그 kernel은 그 오래된 프로세스의 PCB에 그것의 context를 저장한다. Context-switch time은 pure overhead이다. 왜냐하면 그 시스템은 switching 하는동안 유용한 일을 할 수 없기 때문이다. Switching 속도는 기계마다 다르고, 메모리 속도에 의존하고, 복사되어야 할 레지스터의 개수, 특별한 명령어의 존재에 따라 다르다. 일반적인 스피드는 몇 밀리세컨드이다.
* 프로세스들에 대한 연산 (Operations)
  • 실해하는 과정 동안, 한 프로세스는 새로운 프로세스들을 생성할지도 모른다. 생성하는 프로세스는 부모 프로세스라고 불려지고, 새로운 프로세스들은 그 프로세스의 자식들이다. 이러한 새로운 프로세스들의 각각은 차례대로 다른 프로세스들을 만들지도 모르고, 프로세스들의 tree를 형성한다.
  • 일반적으로 한 프로세스가 child process를 생성할 때, 그 child process는 그것의 task를 수행하는데 어떤 자원들 (CPU  시간,  메모리, 파일들, I/O장치)이 필요할 것이다. 자식 프로세스는 운영체제로부터 그것의 자원을 직접적으로 얻을 수 있을지도 모르고, 부모 프로세스의 자원의 부분집합에 제약될지도 모른다. 그 부모는 그것의 자식 중에서 그것의 자원들을 분할해야만 하거나, 어떤 자원들을 그것의 자식들과 공유할 수 있어야 할 지도 모른다. 자식 프로세스를 그 부모의 자원들의 한 부분집합에 제한하는 것은 너무 많은 자식 프로세스를 만들어서 어떤 프로세스가 그 시스템을 과부하시키는 것을 막는다.
  • 다양한 물리/논리적 자원들을 공급하는 것 외에도, 부모 프로세스는 그 자식 프로세스에 초기화 데이터(입력)을 넘길지도 모른다. 한 프로세스가 새로운 프로세스를 생성할 때 실행에 대해 두 가지 가능성이 존재한다 :
    • 그 부모가 그것의 자식과 함께 병행하여 계속해서 실행된다.
    • 그 부모는 그것 자식의 몇 개 또는 모든 자식이 종료할 때 까지 기다린다.
  • 그 새로운 프로세스에 대해 또한 두 가지 address-space 가능성이 있다:
    • 그 child process는 그 부모 프로세스의 복사본이다 (그것은 부모와 같은 프로그램과 데이터를 가진다).
    • 그 child process는 새로운 프로그램이 그것에 불러와지도록 한다.
  • 한 프로세스는 그것이 그것의 마지막 명령어를 실행하고 운영체제가 exit() 시스템 호출을 사용하여 그것을 제거하도록 요청할 때 종료된다. 그 시점에서, 그 프로세스는 status value를 (일반적으로 정수) 그것의 부모 프로세스에게 (wait() system call을 통해) 반환할지도 모른다  physical/virtual memory, open files, I/O buffers를 포함한 그 프로세스의 모든 자원들은 운영체제에 의해 해제된다. 종료는 다른 상황에서 또한 발생할 수 있다. 한 프로세스는 적절한 시스템 호출을 통해 또 다른 프로세스의 종류를 발생시킬 수 있다. 보통 그러한 시스템 호출은 종료되어야 할 프로세스의 부모에 의해서만 불러와질 수 있다. 만약 그렇지 않다면, 사용자들은 임의로 서로의 jobs을 없앨 수 있다. 한 부모가 자식들을 종료시키려면, 그것의 자식들의 identities를 알아야 할필요가 있다는 것에 주목해야 한다. 따라서, 한 프로세스가 새로운 프로세스를 생성할 때, 그 새로이 생성된 프로세스의 identity가 부모에게 넘겨진다.
  • 한 부모는 다음과 같은 여러가지 이유로 그것의 자식들 중 하나의 실행을 종료시킬지도 모른다:
    • 그 자식이 할당된 자원을 초과하여 사용했다 (이것이 발생했는지 결정하기 위해, 그 부모는 그것의 자식들의 상태를 조사하는 메커니즘을 가져야 한다)
    • 그 자식에게 할당된 task가 더 이상 요구되지 않는다.
    • 그 부모가 종료중이고, 운영체제는 한 자식이 그것의 부모가 종료했다면 계속하도록 허용하지 않는다.
  • 어떤 시스템은 그것의 부모가 종료한다면 한 자식이 존재하도록 허용하지 않는다. 그러한 시스템에서, 한 프로세스가 종료된다면, 모든 그것의 자식들은 종료되어야 한다. cascading termination이라고 불리는 이러한 현상은 보통 운영체제에 의해 시작된다.
  • 종료가 되었지만, 그것의 부모가 wait()을 아직 호추하지 않은 프로세스는 zombie process라고 알려져있다. parent가 wait()을 호출하기만 한다면, zombie process의 process identifier와 process table에서의 그것의 entry가 해제된다.
* 프로세스 간 의사소통
  • 운영체제에서 병행하여 실행되는 프로세스들은 독립적인 프로세스이거나 협력적인 프로세스일지도 모른다. 한 프로세스는 그것이 그 시스템에서 실행주인 다른 프로세스에게 영향을 줄 수 없거나 영향받지 않는다면 independent하다. 어떤 다른 프로세스와 데이터를 공유하지 않는 어떤 프로세스든 independent하다. 한 프로세스는 그것이 시스템에서 작동하는 다른 프로세스들에 영향을 주거나 영향을 받는다면 cooperating이다. 명백히 다른 프로세스들과 데이터를 공유하는 프로세스들은 cooperating process이다.
  • process cooperation을 허용하는 환경을 제공하는 몇 가지 이유가 있다:
    • Information sharing : 몇 사용자들은 같은 정보의 조각에 관심있을지도 모르기 때문에 (예를들어, 공유 파일), 우리는 그러한 정보에 concurrent access를 허용하는 환경을 제공해야 한다.
    • Computation speedup : 만약 우리가 특정한 작업이 더 빠르게 작동하길 원한다면, 우리는 그것을 subtasks로 분해하고, 그것들 각각이 다른 것들과 함께 병렬로 실행될 것이다. 그러한 가속은 그 컴퓨터가 여러 개의 프로세싱 코어를 가져야만 얻어질 수 있다.
    • Modularity : 우리는 modular 방식으로 시스템을 구성하길 원한다. 그리고 그 시스템 함수들을 별개의 프로세스들 또는 쓰레드들로 나누면서.
    • Convenience : 심지어 단일 사용자는 동시에 여러 tasks에 작업할지도 모른다. 예를들어, 한 사용자는 병렬로 편집하고 음악을 듣고  컴파일할지도 모른다.
  • 협력 프로세스들은 그것들이 데이터와 정보를 교환하도록 하는 interprocess communication (IPC) 메커니즘을 요구한다. 프로세스 간의 의사소통의 두 개의 기본 모델이 있다 : shared memorymessage passing. shared-memory 모델에서, 협력 프로세스들에 의해 공유되는 메모리 영역이 확립된다. 프로세스들은 그러고나서 공유된 영역에 데이터를 읽거나 써서 정보를 교환할 수 있다. message-passing 모델에서, 의사소통은 협력 프로세스들 사이에서 교환되는 메세지 방법으로 발생한다. 언급된 두 모델들 OS에서 흔하고, 많은 시스템들은 둘 다 구현한다. Message passing은 작은 양의 데이터를 교환하는데 유용한데, 왜냐하면 어떠한 충돌도 피해질 필요가 없기 때문이다. Message passing은 shared memory보다 분산 시스템에서 구현하기에 더 쉽다. shared memory는 message passing보다 더 빠르다. 왜냐하면 message-passing systems은 일반적으로 system calls을사용하여 구현되고, 따라서 kernel 개입의 좀 더 시간을 많이 소비하는 task를 요구하기 때문이다. shared-memory systems에서, 시스템 호출은 shared-memory regions을 형성하기 위해서만 요구된다. 일단 설정되기만 한다면, 모든접근은 routine memory access로 다뤄지고, 커널로부터 어떠한 보조도 요구되지 않는다. 몇 가지 프로세싱 코어를 가진 시스템에 대한 최근 연구는, message passing이 그러한 시스템에서 shared memory보다 더 좋은 성능을 제공한다고 가리킨다. Shared memory는 cache coherency issues를 겪게 되는데, 그것은 shared data가 몇 가지 캐시를 따라서 이동하기 때문에 발생한다. 프로세싱 코어가 증가함에 따라, 우리는 message passing이 IPC에 대해 선호되는 선호되는 메커니즘인 것을 보게되는 것이 가능하다.
  • 일반적으로 한 shared-memory region은 그 shared-memory segment를 생성하는 프로세스의 주소 공간에 있다. 이 shared-memory segment를 사용하여 의사소통 하길 원하는 다른 프로세스들은 그들의 주소 공간에 그것을 붙여야만 한다. 일반적으로 OS는 한 프로세스가 다른 프로세스의 메모리에 접근하는 것을 막으려고 한다. Shared memory는 두 개 이상의 프로세스가 이 제한을 제거하도록 동의하는 것을 요구한다.그들은 그러고나서 공유된 영역에서 데이터를 읽고 써서 정보를 교환할 수 있다. 그 데이터의 형식과 위치는 이러한 프로세스들에 의해 결정되고, OS 제어안에 있지 않다. 또한 그 프로세스들은 그들이 같은 위치에 동시에 write하고 있지 않다는 것을 보장하는데 책임이 있다.
  • 협력 프로세스의 개념을 보여주기 위해, producer-consumer 문제를 고려하자. producer process는 consumer process에 의해 소비되는 정보를 생성한다. 그것은 client-server 패러다임에 대해 유용한 비유를 제공한다. producer-consumer problem에 대한 한 가지 솔루션을 shared memory를 사용하는 것이다. producer와 consumer 프로세스가 병행하게 실행하도록 하여, 우리는 프로듀서에 의해 채워질 수 있고 소비자에의해 비워질 수 있는 이용가능한 아이템들의 버퍼를 가져야 한다. 이 버퍼는 생산자/소비자 프로세스에 의해 공유되는메모리영역에 있을 것이다.
  • Message passing은 같은 주소 공간을 공유하지 않고, 프로세스들이 의사소통하고 그것들의 행동을 동기화하도록 하는 기제를 제공한다. 그것은 특히 distributed environment에서 유용한데, 거기에서 의사소통 하는 프로세스들은 네트워크에 연결된 다른 컴퓨터에 있을지도 모른다. 예를들어, 인터넷 chat program은 chat 참가자들이 메세지들을 교환하여 서로 의사소통할 수 있도록 설계될 수 있다. message-passing 기능은 적어도 두 개의 연산을 제공한다 :
    • send(message)
    • receive(message)
  • 한 프로세스에 의해 보내진 메세지들은 크기가 고정이거나 가변할 수 있다. 만약 fixed-sized messages만 보내질 수 있다면, system-level implementation은 간단하다. 그러나, 이러한 제한은 프로그래밍의 일을 더 어렵게 만든다. 역으로, 가변 사이즈 메세지는 더 복잡한 system-level 구현을 요구하지만, 프로그래밍 task는 더 간단해 진다.
  • 만약 프로세스들 P와 Q가 의사소통하길 운한다면, 그들은 서로에게 메세지를 보내고 받아야만 한다: 그들사이에 한 communication link가 존재해야 한다. 이 link는 다양한 방식으로 구현될 수 있다. logically하게 한 link와 send()/receive() 연산을 구현하는 몇 가지 방법들이 있다:
    • Direct or indirect communication
    • Synchronous or asynchronous communication
    • Automatic or explicit buffering
  • 의사소통 하길 원하는 프로세스들은 서로를 언급하는 방법을 가져야만 한다. 그들은 direct or indirect communication 둘 중 하나를 사용할 수 있다. direct communication에서 의사소통 하길 원하는 각 프로세스는 의사소통의 수령자와 보내는 사람을 explicitly하게 이름지어야 한다. 이 전략에서, send()와 receive() primitives는 다음으로 정의된다:
    • send(P, message) - process P에게 한 message를 보내라
    • receive(Q, message) - process Q로부터 한 message를 받아라.
  • 이 전략에서 communication link는 다음의 특성을 갖는다:
    • 의사소통 하길 원하는 프로세스들의 모든 쌍 사이에 한 link가 자동으로 만들어진다. 그 프로세스들은 의사소통하는 서로의 identity만을 알 필요가 있다.
    • 한 link는 정확히 두 개의 프로세스들과 관련된다.
    • 각 프로세스의 쌍 사이에, 정확히 한 개의 link가 존재한다.
  • 이 전략은 addressing에서 symmetry를 보여준다; 즉, 보내는 프로세스와 받는 프로세스 둘 다 의사소통하기 위해 이름을 지어야 한다.이 전략의 변형된 것은addressing에서 asymmetry를 이용한다. 여기에서 보내는 사람만 수령자를 이름을 댄다. 그 수령자는 보낸 사람의 이름을 대는 것이 요구되지 않는다. 이 전략에서 send()와 receive() primitives는 다음으로 정의된다:
    • send(P, message) - 프로세스 P에 한 message를 보내라
    • receive(id, message) - 어떤 프로세스로 부터 한 message를 받아들여라. 그 변수 id는 의사소통이 일어나는 프로세스의 이름에 대해 설정된다.
  • 이 전략 둘 다 (symmetric and asymmetric)의 단점은 최종 프로세스 정의의 제한된 modularity이다. 한 프로세스의 identifier를 바꾸는 것은 모든 다른 프로세스 정의들을 조사하게 만들지도 모른다.
  • indirect communication으로, 그 메세지들은 mailboxes 또는 ports로부터 주고 받아진다. mailbox는 메세지가 프로세스에 의해 위치될 수 있고 메세지들이 제거될 수 있는 한 오브젝트로서 추상적으로 보아질 수 있다. 한 프로세스는 많은 다른 mailboxes를 통해 또 다른 프로세스와 의사소통 할 수 있지만, 두 프로세스들은은 그들이 공유된 mailbox를 가져야만 의사소통할 수 있다. 이 전략으로, communication link는 다음의 특성을 갖는다:
    • 한 Link는 프로세스들의 한 쌍 사이에서 만들어지는데, 그 쌍의 두 멤버 모두 shared mailbox를 가져야만 한다.
    • 한 link는 두 개 이상의 프로세스들과 연관될지도 모른다.
    • 의사소통하는 프로세스들의 각 쌍 사이에서, 많은 다른 links들이 존재할지 모르고, 각 link는 한 mail box와 대응된다.
  • 프로세스들 사이의 커뮤니케이션은 send()와 receive() primitives에 대한 호출을 통해 발생할 수 있다. 각 primitive를 구현하는데 다른 설계 옵션들이 있다. Message passing은 synchronousasynchronous라고 알려진 blocking 또는 nonblocking 둘 중 하나일 것이다. (이 교재 도처에, 너는 다양한 운영체제 알고리즘들과 관련하여 동기와 비동기 행동의 개념을 만날 것이다)
    • Blocking send : 보내는 프로세스는 그 메세지가 받는 프로세스 또는 mailbox에 의해 받아질 때 까지 blocked 된다.
    • Nonblocking send : 그 보내는 프로세스는 그 메세지를 보내고 연산을 재개한다.
    • Blocking receive : 그 receiver는 한 메세지가 이용가능할 때 까지 block한다.
    • Nonblocking receive : 그 receiver는 유효한 메세지 또는 null 둘 중 하나를 가져온다.
  • 커뮤니케이션이 direct or indirect든, 의사소통 하는 프로세스들에 의해 교환되는 메세지들은 임의의 큐에 있다. 기본적으로 그러한 큐들은 세 가지 방법으로 구현될 수 있다: (zero-capacity는 가끔 buffering이 없는 message system이라고 언급되고, 다른 경우들은 automatic buffering을 가진 systems으로 언급된다.
    • Zero capacity : 그 큐는 zero의 최대 길이를 갖는다; 따라서, 그 link는 그것에 기다리는 어떠한 메세지도 가질 수 없다. 이 경우에, sender는 수령자가 그 메세지를 받을 때 까지 block 해야 한다.
    • Bounded capacity : 그 queue는 유한의 길이 n을 갖는다; 따라서, 최대 n개의 메세지들만 그 안에 있을 수 있다. 만약 한 새로운 메세지가 보내졌을 때 큐가 꽉차 있지 않다면, 그 메세지는 큐에 위치하고 (그 메세지는 복사되거나 그 메세지에 대한 포인터가 유지된다), 그리고 그 sener는 기다림 없이 실행을 계속할 수 있다. 그러나, 그 link의 capacity는 유한이다. 만약 그 link가 full이라면, 그 sender는 큐에서 공간이 이용가능할 때 까지 봉쇄 되어야 한다.
    • Unbounded capacity : 그 큐의 길이는 잠재적으로 무한이다; 따라서, 어떤 수의 메세지들인지 그것안에 기다릴 수 있다. 그 sender는 결코 봉쇄되지 않는다.
* 프로세스 간 통신 시스템의 예제
POSIX API for shared memory
message passing in the Mach operating system
Windows using shared memory as a mechanism for providing certain types of message passing.

  • POSIX API for shared memory
  • Mach에서 모든 task간 정보를 포함하여 모든 의사소통은 messages로 수행된다. Messages는 Mach에서 ports라고 불리는 mailboxes를 통해 주고 받아진다. 심지어 system calls는 messages에 의해 만들어진다. 한 task가 생성될 때, Kernel mailbox와 Notify mailbox인 두 개의 특별한 mailboxes가 생성된다. 그 kernel은 task과 의사소통하기 위해 그 Kernel mailbox를 사용하고, Notify port로 이벤트 발생의 알림을 보낸다. 오직 세 개의 system calls이 message transfer를 위해 필요하다. msg_send() call은 mailbox로 메세지를 보낸다. 한 메세지는 msg_receive()를 통해 받아진다. Remote procedure calls(RPCs)는 msg_rpc()를 통해 실행된다. 이것은 한 메세지를 보내고, 그 보내는 사람으로부터 정확히 한 개의 return message를 기다린다. message systems이 가진 주요한 문제는 일반적으로 messages의 double copying에 의해 발생하는 좋지 않은 성능이였다 : 그 메세지는 처음에 보내는사람에서 mailbox로 복사되고, mailbox에서 receiver로 복사된다. Mach message system은 virtual-memory-management techniques을 이용하여 double-copy 연산을 피하려고 한다.
  • 윈도우즈 운영체제는 기능성을 증가하고 새로운 기능 구현에 필요한 시간을 줄이기 위해 modularity를 이용하는 현대 설계의 예시이다. 윈도우즈는 여러 운영체제 환경, 또는 subsystems에 대한 지원을 제공한다. 어플리케이션 프로그램들은 message-passing mechanism을 통해 이러한 subsystems과 의사소통한다. 따라서, 어플리케이션 프로그램들은 subsystem server의 clients로 고려될 수 있다. 윈도우즈에서 message-passing facility는 advanced local procedure call (ALPC) 기능으로 불려진다. 그것은 같은 기계에서 두 프로세스들 사이에서 의사소통을 위해 사용된다. 그것은 널리 사용되는 standard remote procedure (RPC) 메커니즘과 유사하지만, 윈도우즈에 최적화되고 특화되었다. Mach처럼, 윈도우즈는 두 프로세스 사이의 연결을 만들고 유지하기 위해 port를 사용한다. 윈도우즈는 두 가지 유형의 포트들을사용한다 : connection portscommunication ports.
* Client-Server 시스템에서의 Communication

  • sockets은 communication을 위한 endpoint로 정의된다. 네트워크를 통해 의사소통하는 프로세스들의 한 쌍은 한 쌍의 소켓들을이용한다 - 각 프로세스에 대해 하나씩. 한 소켓은 port number로 연결된 IP 주소로 인식된다. 일반적으로 소켓들은 client-server 아키텍쳐를 사용한다.
  • 원격 서비스의 가장 흔한 형태들중의 하나는 Remote Procedure Call(RPC) 패러다임이다. 이것은 네트워크 연결을 가진 시스템 사이에서 사용하는 procedure-call mechanism을 추상화하는 방식으로서 설계되었다. 그것은 설명된 IPC 메커티즘과 여러 면에서 비슷하고, 그러한 시스템 위에서 보통 구성된다. 그러나, 그 프로세스들이 별개의 시스템에서 실행하는 환경을 다루려고 하기 때문에, 우리는 remote service를 제공하는 메세지 기반의 커뮤니케이션 전략을 사용해야만한다. RPC 커뮤니케이션에서 교환되는 메세지들은 잘 구조화되어있고 따라서 더 이상 데이터의 패킷들이 아니다. 각 메세지는 remote system에서 한 port를 듣고 있는 RPC demon으로 addressed된다. 각각은 실행할 함수와 그 함수에 넘겨야 할 파라미터를 명시하는 identifier를 포함한다. 그 함수는 요청대로 실행되고, 어떤 결과는 별개의 메세지에 요청자에게 다시 보내진다. 
  • 어떤 시스템은 (big-endian이라고 알려진) most significant byte를 처음에 저장하지만, 다른 시스템들 (little-endian이라고 알려진) least significant byte를처음에 저장한다. 이러한 차이를 해결하기 위해 많은 RPC 시스템들은 데이터의 machine-independent 표기를 정의한다. 한 그러한 표기는 external data representation (XDR)로 알려져 있다. client side에서 parameter marshaling은 machine-dependent data를 XDR로 서버에 보내기전에 변환하는 것을 포함한다. 서버 단에서, XDR data는 unmarshalled 되고, 그 서버를 위한 machine-dependent representation으로 변환된다.
  • pipe는 두 프로세스가 의사소통하게하는 conduit이다. Pipes는 초기 UNIX 시스템에서 처음 IPC 메커니즘들 중 하나였다. 그것들은 한계가 있을지라도 일반적으로 프로세스가 서로 의사소통 하게 하는 더 간단한 방법들 중 하나를 제공한다. 파이프 구현에 있어서, 네 개의 문제가 고려되어야 한다:
    • 1. 그 PIPE는 양방향 통신을 허용하는가? 통신이 방향이 없는가?
    • 만약 two-way communication이 허용된다면, half duplex (data는 한 번에 항 방향으로만 이동할 수 있다) 또는 full duplex인가 (data는 양 방향으로 동시에 움직일 수 있다)?
    • 한 관계가 (parent-child같은) 통신 프로세스들 사이에 존재해야 하는가?
    • pipes는 네트워크를 통해 통신할 수 있는가? 또는 통신하는 프로세스들은 같은 machine에 있어야 하는가?
  • Ordinary pipes는 표준 producer-consumer 방식으로 두 프로세스들이 통신하게한다: 그 생산자는 그 파이프의 한 쪽 끝에 write하고, consumer는 다른 끝에 reads 한다. 결과적으로 ordinary pipes는 단방향이다. 이것은 one-way 통신을 허용한다. 만약 two-way 통신이 요구된다면, 두 개의 파이프들이 사용되어야 하고, 각 pipe는 다른 방향으로 data를 보낸다. Ordinary pipes는 UNIX와 Windows 시스템에서 둘 다 통신하는 프로세스 사이에 parent-child 관계를 요구한다. 이것은 같은 machine에 있는 프로세스들 사이의 통신에만 이러한 파이플들이 사용될 수 있다는것을 의미한다.
  • Named pipes는 양방향일 수 있고, parent-child 관계가 요구되지 않는다. 한 개의 named pipe가 만들어진다면, 몇 개의 프로세스들은 그것을 통신을 위해 사용할 수 있다. Named pipes는 UNIX 시스템에서 FIFO로 언급된다. 만들어진다면, 그것들은 파일 시스템에서 일반적인 파일들로 나타난다. 그것은 file system에서 explicitly하게 제거될 떄 까지 계속해서 존재할 것이다. FIFO가 양방향 통신을 허용할지라도, half-duplex 전송만이 허가된다. 부가적으로 통신 프로세스들이 같은 기계에 있어야 한다. 만약 기계간 통신이 요구된다면, 소켓이 사용되어야 한다.
  • 윈도우즈 시스템에서 Named pipes는 UNIX보다 더 부유한 통신 메커니즘을 제공한다. Full-duplex 통신이 허용되고, 통신하는 프로세스들은 같은 또는 다른 기계들 중 하나에 있어도 된다. 부가적으로 byte 지향 data는 UNIX FIFO를 통해 전송되지만, 윈도우즈 시스템은 byte- or message- oriented data를 허용한다. 

댓글 없음:

댓글 쓰기