‘Operating System Concepts 8th’를 정리한 글이다.
3.1 프로세스 개념
초기 컴퓨터 시스템은 한 번에 하나의 프로그램만이 실행되도록 허용되었다. 하나의 프로그램이 시스템에 대한 완전한 제어를 가지고, 시스템의 모든 자원에 접근할 수 있었다.
반면 오늘날의 컴퓨터 시스템들은 다수의 프로그램이 병행 실행되는 것을 허용한다. 이런 시스템이 견고하게 제어하고 보다 구획화될 것을 필요로 한다. 이런 필요성이 프로세스의 개념을 낳았으며, 프로세스란 실행 중인 프로그램을 말한다.
3.1.1 프로세스
비공식적으로 프로세스란 실행 중인 프로그램이다.
프로세스는 프로그램 카운터의 값과 처리기 레지스터의 내용으로 대표되는 현재 활동을 포함한다.
프로세스는 함수의 매개변수, 복귀 주소, 로컬 변수와 같은 임시적인 자료를 갖는 프로세스 스택과 전역 변수들을 수록하는 데이터 섹션, 실행 중에 동적으로 할당되는 메모리인 힙을 포함한다.

프로그램 그 자체는 프로세스가 아니다. 프로그램은 명령어 리스트를 내용으로 가진 디스크에 저장된 파일(실행 파일이라고도 부름)과 같이 수동적인 존재이고 프로세스는 다음에 실행할 명령어를 지정하는 프로그램 카운터 및 관련된 자원의 집합을 가진 능동적 존재다.
3.1.2 프로세스 상태(Process State)
프로세스는 다음과 같은 상태 중 하나가 된다
- 새로운(new) : 프로세스가 생성 중이다
- 실행(running) : 명령어들이 실행되고 있는 중이다
- 대기(waiting) : 프로세스가 어떤 사건(입출력 완료 또는 신호의 수신 같은)이 일어나기를 기다린다.
- 준비완료(ready) : 프로세스가 처리기에 할당되기를 기다린다.
- 종료(terminated) : 프로세스가 실행을 종료하였다.

3.1.3 프로세스 제어 블록(Process Control Block)
각 프로세스는 운영체제에서 프로세스 제어 블록(PCB, Process Control Block)에 의해 표현된다.

- 프로세스 상태 : 상태는 새로운(new), 준비완료(ready), 실행(running), 대기(waiting), 또는 정지(halted) 상태 등이다.
- 프로그램 카운터 : 프로그램 카운터는 이 프로세스가 다음에 실행할 명령어의 주소를 가리킨다.
- CPU 레지스터들 : 레지스터에는 누산기, 인덱스 레지스터, 스택 레지스터, 범용 레지스터들과 상태 코드 정보가 포함된다. 이 상태 정보는 인터럽트 발생 시 프로그램 카운터와 함께 저장된다
- CPU-스케줄링 정보 : 이 정보는 프로세스 우선순위, 스케줄 큐에 대한 포인터와 다른 스케줄 매개변수들을 포함한다
- 메모리 관리 정보 : 이 정보는 운영체제가 지원하는 메모리 시스템에 따라 기준레지스터와 한계 레지스터의 값, 페이지 테이블, 세그먼트 테이블 등의 정보를 포함한다.
- 회계 정보 : 이 정보는 CPU가 사용된 양과 사용된 실제 시간, 시간제한, 계정정보, 잡(job) 또는 프로세스 번호 등을 포함한다.
- 입출력 상태 정보 : 이 정보는 이 프로세스에 할당된 입출력장치들과 열린 파일의 목록 등을 포함한다.

3.1.4 스레드(Threads)
현대의 운영체제는 프로세스 개념을 확장하여 한 프로세스가 여러 실행 스레드를 가질 수 있도록 하여 한순간에 하나 이상의 일을 실행할 수 있게 된다. 스레드를 지원하는 시스템에서 PCB는 각 스레드에 관한 정보를 포함하도록 확장된다.
3.2 프로세스 스케줄링
다중 프로그래밍의 목적은 CPU 이용을 최대화하기 위해 항상 어떤 프로세스가 실행 중이도록 하는 데 있다. 시분할의 목적은 각 프로그램이 실행되는 동안 사용자가 상호작용할 수 있도록 프로세스들 사이에서 CPU를 빈번하게 교체하는 것이다.
3.2.1 스케줄링 큐
프로세스가 시스템에 들어오면, 이들은 잡 큐에 놓여진다. 이 큐는 시스템 안의 모든 프로세스로 구성된다.
주 메모리에 존재하며, 준비완료 상태에서 실행을 대기하는 프로세스들은 준비완료 큐(ready queue)라 불리는 리스트에 유지된다. 이 큐는 일반적으로 연결 리스트로 저장된다.
프로세스가 디스크 같은 공유장치에 입출력 요청을 했다고 가정했을 때 다른 프로세스들의 입출력 요청으로 인해 디스크가 바쁠 수 있다. 그러므로 프로세스는 디스크를 기다려야 할 수 있기에 특정 입출력 장치를 대기하는 장치 큐(device queue)에 들어간다.
프로세스가 준비완료 큐에서 대기하다 CPU에 할당되어 실행되면 다음 사건들 중 하나가 발생할 수 있다.
- 프로세스가 입출력을 요청하여 입출력 큐에 넣어질 수 있다.
- 프로세스가 새로운 서브프로세스를 생성하고 그 프로세스의 종료를 기다릴 수 있다.
- 프로세스가 인터럽트의 결과에 따라 강제로 CPU로부터 제거되어 준비완료 큐에 다시 놓일 수 있다.
처음의 두 경우에는 프로세스가 대기 상태에서 준비완료 상태로 전환되고 다시 준비완료 큐에 넣어진다. 프로세스가 종료될 때까지 이 주기를 반복하며, 종료되면 모든 큐에서 삭제되고 그 자신의 PCB와 자원을 반납한다.
3.2.2 스케줄러
일괄처리 시스템에서는 즉시 실행될 수 있는 것보다 더 많은 프로세스들이 종종 제출된다. 이들 프로세스들은 대용량 메모리(전형적으로 디스크)에 저장되어 나중에 실행될 때까지 그곳에 유지된다.
장기 스케줄러는 이 풀에서 프로세스들을 선택하여 실행하기 위해 메모리로 적재한다.
단기 스케줄러는 실행 준비가 완료되어 있는 프로세스들 중에 선택하며, 이들 중 하나에게 CPU를 할당한다.
이들 두 스케줄러 사이의 주요한 차이점은 실행 빈도에 있다. 단기 스케줄러는 CPU를 위해 자주 새로운 프로세스를 선택한다. 실행 간격이 짧기 때문에 매우 빨라야만 한다.
반면에 장기 스케줄러는 실행 빈도수가 훨씬 적다. 장기 스케줄러는 프로세스가 시스템을 떠날 때만 호출될 필요가 있을 수 있다. 실행 간격이 비교적 크기 때문에 장기 스케줄러는 실행할 프로세스를 선택하는데 시간을 더 사용해도 된다.
입출력 중심 프로세스는 연산보다 입출력에, CPU 중심 프로세스는 입출력보다 연산에 시간을 더 소요한다. 장기 스케줄러는 입출력 중심과 CPU 중심 프로세스들이 적절히 혼합되도록 선택하는 것이 중요하다. 만일 모든 프로세스들이 CPU 중심이라면 입출력 대기 큐는 항상 비어있게 되고 시스템은 균형을 잃게 된다.
예를 들어 Microsoft Windows 같은 시분할 시스템은 장기 스케줄러가 없으며, 모든 새로운 프로세스를 단기 스케줄러를 위해 단순히 메모리에 넣는다. 이들 시스템의 안정성은 물리적인 제한(이를테면 가용 단말기의 수)나 사용자들의 자체 조정 본능에 의존한다.
시분할 시스템과 같은 일부 운영체제는 추가로 중간 수준의 스케줄링을 도입한다. 중기 스케줄러의 핵심 아이디어는 메모리에서 프로세스들을 제거하여, 즉 CPU를 위한 경쟁에서 제거하여 다중 프로그래밍의 정도를 완화하는 것이 바람직할 때도 있다는 것이다. 차후에 다시 프로세스를 메모리로 불러와서 중단되었던 지점에서 실행을 재개하는데 이런 기법을 스와핑(swapping)이라고 한다.
3.2.3 문맥 교환(Context Switch)
인터럽트는 운영체제가 CPU를 현재 작업에서 뺏어 내어 커널 루틴을 실행할 수 있게 한다. 인터럽트가 발생하면 시스템은 인터럽트 처리가 끝난 후에 문맥을 복구할 수 있도록 현재 실행 중 프로세스의 현재 문맥을 저장한다.
CPU를 다른 프로세스로 교환하려면 현재 프로세스의 상태를 저장하고 다른 프로세스의 저장된 상태를 복구하는 작업이 필요하다. 이 작업을 문맥 교환(context switch)이라 한다.
문맥 교환이 진행될 동안 시스템은 유용한 일을 못 하기 때문에 순수한 오버헤드가 된다.
3.3 프로세스에 대한 연산
대부분 시스템 내의 프로세스들은 병행 실행될 수 있으며, 반드시 동적으로 생성되고 제거될 수 있다.
3.3.1 프로세스 생성
프로세스는 실행 도중에 프로세스 생성 시스템 호출을 통해 여러 개의 새로운 프로세스들을 생성할 수 있다. 생성하는 프로세스를 부모 프로세스라고 부르고, 새로운 프로세스는 자식 프로세스라 부른다.
대부분 운영체제는 유일한 프로세스 식별자(pid)에 의해 프로세스를 구분하는데, 이 식별자는 통상적으로 정수 값이다.

프로세스는 자신의 태스크(task)를 달성하려면 자원들(CPU시간, 메모리, 파일, 입출력장치)이 필요하다. 자식 프로세스는 운영체제로부터 직접 자원을 얻거나, 혹은 부모 프로세스 자원의 부분 집합을 사용하도록 강요받을 수 있다.
프로세스가 새로운 프로세스를 생성할 때 실행과 관련한 두 가지 가능성이 있다.
- 부모가 계속해서 자식과 병렬로 실행된다.
- 부모가 모든 자식 또는 일부 자식이 끝날 때까지 기다린다.
새로운 프로세스들의 주소 공간 측면에서 볼 때 다음과 같은 두 가지 가능성이 있다.
- 자식 프로세스는 부모 프로세스의 복사본이다(자식은 부모와 같은 프로그램, 데이터를 갖는다)
- 자식 프로세스가 자신에게 적재될 새로운 프로그램을 갖는다.
두 프로세스(부모와 자식)은 fork() 의 반환코드가 서로 다르다. 자식은 부모에게 자신의 PID를 반환하지만 부모는 자식에게 “0”을 반환한다.
부모는 더 많은 자식을 생성할 수 있으며, 또는 자식이 실행하는 동안 할 일이 없으면, 자식이 종료될 때까지 준비완료 큐에서 자신을 제거하기 위해 wait() 시스템 호출을 호출한다.

3.3.2 프로세스 종료
프로세스가 마지막 문장의 실행을 끝내고, exit 시스템 호출을 사용하여 운영체제에게 자신의 제거를 요청하면 종료된다. 자신의 부모가 있다면 부모 프로세스에게(wait 시스템 호출을 통해) 상태 값(통상 정수값)을 반환할 수 있다. 물리 메모리, 가상 메모리, 열린 파일, 입출력 버퍼를 포함한 프로세스의 모든 자원이 운영체제로 반납된다.
한 프로세스가 다른 프로세스의 종료를 유발할 수 있다. 보통 그런 시스템 호출은 오직 종료될 프로세스의 부모만이 호출할 수 있다. 그렇지 않으면, 사용자가 서로의 다른 작업을 임의적으로 중단(kill)시킬 수 있을 것이다.
부모는 다음과 같이 여러 가지 이유로 인하여 자식들 중 하나의 실행을 종료할 수 있다.
- 자식이 자신에게 할당된 자원을 초과하여 사용할 때, 이때는 부모가 자식들의 상태를 검사할 수 있는 방편이 주어져야 한다.
- 자식에게 할당된 태스크(task)가 더 이상 필요 없을 때
- 부모가 exit하는데, 운영체제는 부모가 exit한 후에 자식이 실행을 계속하는 것을 허용하지 않는 경우
VMS를 포함한 몇몇 시스템에서는 부모 프로세스의 종료 이후에 자식 프로세스는 존재할 수 없다. 그런 시스템에서는 부모가 종료되면(정상이건 비정상이건) 자식 프로세스가 종료되어야 한다. 이것을 연속적 종료라 부르며 이 작업은 운영체제가 한다.
UNIX에서는 부모가 종료되면 모든 자식은 init 프로세스를 그들의 새로운 부모로 지정 받는다. 따라서 자식들은 여전히 그들의 상태와 실행 통계를 수집할 부모를 갖게 된다.
3.4 프로세스간 통신
프로세스가 시세틈에서 실행 중인 다른 프로세스들에게 영향을 주거나 받지 않으면 독립적인 프로세스, 영향을 주거나 받는다면 협력적인 프로세스라 한다.
프로세스 협력을 허용하는 환경을 제공하는 데는 몇 가지 이유가 있다.
- 정보 공유(information sharing) : 여러 사용자가 동일한 정보(예로 공유 파일 등)에 관심사가 있다면 그런 정보를 병행적으로 접근할 수 있는 환경을 제공해야 한다.
- 계산 가속화(computation speedup) : 특정 태스크(task)를 빨리 실행하고자 한다면, 서브태스크로 나누어, 이들 각각이 다른 서브태스크들과 병렬로 실행되게 해야 한다.
- 모듈성(modularity) : 2장에서 논의했던 것 처럼 시스템 기능을 별도의 프로세스들 또는 스레드들로 나누어 모듈식 형태로 구성하기 원할 수 있다.
- 편의성(convenience) : 개별 사용자들이 동시에 작업할 많은 태스크(task)를 가질 수 있다.
협렬적 프로세스들은 데이터와 정보를 교환할 수 있는 프로세스간 통신(interprocess communication, IPC) 기법을 필요로 한다. 프로세스간 통신에는 기본적으로 1) 공유 메모리와 2) 메시지 전달의 두 가지 모델이 있다.

많은 운영체제들이 두 가지를 모두 구현한다. 메시지 전달 모델은 충돌을 회피할 필요가 없기에 적은 양의 데이터를 교환하는데 유용하다. 공유 메모리 모델은 최대 속도와 편이를 제공한다.
3.4.1 공유 메모리 시스템
공유 메모리를 사용하는 프로세스 간 통신에서는 통신하는 프로세스들이 공유 메모리 영역을 구축해야 한다. 통상 공유 메모리 영역은 공유 메모리 세그먼트를 생성하는 프로세스의 주소 공간에 위치한다. 이 공유 메모리 세그먼트를 이용하여 통신하고자 하는 다른 프로세스들은 이 세그먼트를 자신의 주소 공간에 추가해야 한다.
일반적으로 운영체제는 한 프로세스가 다른 프로세스의 메모리에 접근하는 것을 금지하기에 이 제약 조건을 제거하는 것에 동의해야 한다.
두 프로세스를 하나는 생산자(정보를 만드는 프로세스)로 소비자(정보를 읽어들이는 프로세스)로 나누는 모델로 비유한다.
생산자와 소비자가 병행으로 실행되려면 정보를 채워 넣고 소모할 수 있는 버퍼가 반드시 사용 가능해야 한다. 이 버퍼는 반드시 동기화가 되어야 생산하지 않은 항목을 소비자가 소비하려고 시도하지 않을 것이다.
두 가지 유형의 버퍼가 사용된다. 무한 버퍼(unbounded buffer)에선 소비자는 새로운 항목을 기다려야만 할 수 있지만, 생산자는 항상 새로운 항목을 생산할 수 있다. 유한 버퍼(bounded buffer)에서는 비어있다면 소비자는 반드시 대기해야 하며, 다 채워있다면 생산자가 대기해야 한다.
생산자와 소비자가 동시에 공유 버퍼를 접근하는 상황에 대한 고려는 6장에서 논의된다.
3.4.2 메시지 전달 시스템
메시지 전달 방식은 프로세스들이 통신을 하고, 그들의 동작을 동기화할 수 있도록 허용하는 기법을 제공한다.
메시지 전달 시스템은 최소한 send, receive 두 가지 연산을 제공한다. 프로세스가 보낸 메시지는 고정 길이일 수도 있고 가변 길이일 수도 있다. 고정 길이는 시스템 수준의 구현은 간단하지만 프로그래밍 작업을 힘들게 하고 가변 길이 메시지는 시스템 구현이 복잡하지만 프로그래밍 작업이 간단해진다.
두 프로세스가 통신을 원할 때 이 둘 간의 연결과 send/receive 연산을 논리적으로 구현하는 다수의 방법들은 다음과 같다.
- 직접 또는 간접 통신
- 동기식 또는 비동기식 통신
- 자동 또는 명시적 버퍼링
3.4.2.1 명명(Naming)
통신을 원하는 프로세스들은 서로를 가리킬 수 있는 방법이 있어야 한다. 직접 통신 하에서, 통신을 원하는 각 프로세스는 통신의 수신자 또는 송신자의 이름을 명시한다.
send(P, message) - 프로세스 p에게 메시지를 전송한다
receive(Q, message) - 프로세스 Q에게 메시지를 수신한다.
이 기법은 대칭성을 보인다. 비대칭 형식으로는
send(P, message) - 프로세스 p에게 메시지를 전송한다
receive(id, message) - 임의의 프로세스로부터 메시지를 수신한다. 변수 id는 통신을 발생시킨 프로세스의 이름으로 설정된다.
이들 대칭적, 비대칭적 기법의 단점은 프로세스를 정확히 지정함으로써 모듈화를 제한한다는 것이다.
간접 통신에서 메시지는 메일박스(mailbox) 또는 포트(port)로 송신되고, 그것으로 수신된다.
send(A, message) - 메시지를 메일박스 A로 송신한다 receive(A, message) - 메시지를 메일박스 A로부터 수신한다.
이 방법은 다음의 성질을 가진다.
- 한 쌍의 프로세스 사이의 연결은 이 프로세스들이 공유 메일박스를 가질 때만 구축된다.
- 연결은 두 개 이상의 프로세스와 연관될 수 있다.
- 통신하고 있는 각 프로세스 사이에는 다수의 다른 연결이 존재할 수 있다. 각 연결마다 하나의 메일박스가 할당된다.
만일 P1, P2, P3이 모두 메일박스 A를 공유할 때 P1이 메시지를 보내면 누가 P1의 메시지를 수신하는가? 이건 선택할 기법에 좌우된다.
- 하나의 링크는 최대 두 개의 프로세스와 연관되도록 허용
- 한 순간 최대 하나의 프로세스가 receive 연산을 실행하도록 허용
- 어느 프로세스가 메시지를 수신할 건지 시스템이 임의로 선택, 시스템은 송신자에게 수신자를 알려줄 수 있음
운영체제는 프로세스에게 다음과 같은 작업을 할 수 있도록 허용하는 메커니즘을 제공해야만 한다.
- 새로운 메일박스를 생성한다
- 메일박스를 통해 메시지를 송신하고 수신한다
- 메일박스를 삭제한다
3.4.2.2 동기화(Synchronization)
메시지 전달은 봉쇄형, 비봉쇄형이 된다.
- 봉쇄형 송신 : 송신 프로세스가 메시지가 수신 프로세스 또는 메일박스에 의해 수신될 때까지 봉쇄
- 비봉쇄형 송신 : 송신 프로세스가 메시지를 보내가 작업을 재시작
- 봉쇄형 수신 : 메시지가 이용 가능할 때까지 수신 프로세스가 봉쇄
- 비봉쇄형 수신 : 수신하는 프로세스가 유효한 메시지 또는 null 값을 받는다
3.4.2.3 버퍼링(Buffering)
통신이 직접적이든 간접적이든 프로세스들에 의해 교환되는 메시지는 임시 큐에 들어간다. 이런 큐를 구현하는 방식은 세 가지다.
- 무용량 : 큐의 최대 길이가 0이다. 이 큐는 자체 안에 대기하는 메시지를 가질 수 없다. 이 경우에 송신자는 수신자가 메시지를 수신할 때까지 송신할 수 없다.
- 유한 용량 : 큐는 유한한 길이 n을 가진다. 큐가 차지 않으면 송신자는 대기하지 않고 실행하지만 큐가 가득 찬다면 가용 공간이 생길 때까지 대기한다.
- 무한 용량 : 큐는 잠재적으로 무한한 길이를 가진다. 송신자는 결코 봉쇄되지 않는다.
무용량의 경우 때로 버퍼링하지 않는 메시지 시스템이라 부른다. 다른 경우는 자동 버퍼링 메시지 시스템이라 부른다.
3.5 IPC 시스템의 사례
(밑은 다음에 정리한다.)
3.5.1 예 : POSIX 공유 메모리
3.5.2 예 : Mach
3.5.3 예 : Windows XP
3.6 클라이언트 서버 환경에서 통신
클라이언ㅌ-서버에서 사용할 수 있는 세 가지 다른 통신 전략에 대해 설명한다. 이 세 가지는 소켓, 원격 프로시저 호출 및 파이프이다.
3.6.1 소켓(Socket)
두 프로세스가 네트워크상에서 통신을 하려면 양 프로세스마다 하나씩, 총 두 개의 소켓이 필요하다.
클라이언트 프로세스가 연결을 요청하면 호스트 컴퓨터가 포트 번호를 부여한다. 이 번호는 1024보다 큰 임의의 정수가 된다(1024 미만의 모든 포트는 well-known 포트로 간주된다)
소켓을 이용한 통신은 분산된 프로세스들 간에 널리 사용되고 효율적이지만 너무 저수준이다. 스레드들 간에 구조화 되지 않은 바이트 스트림만을 통신하도록 하기 때문이다. 이런 원시적인 바이트 스트림 데이터를 구조화하여 해석하는 것은 클라이언트와 서버의 책임인다.
3.6.2 원격 프로시저 호출(Remote Procedure Calls, PRC)
이것은 IPC와 많은 측면에서 유사하며, 사실 그와 같은 IPC 기반 위에 만들어진다. 서로 다른 시스템에서 실행되기에 원격 서비스를 제공하기 위해 메시지 기반 통신을 해야한다. 각 메시지에는 원격지 포트에서 listen 중인 RPC 디먼의 주소가 지정되어 있고 실행되어야 할 함수의 식별자, 그 함수에게 전달되어야 할 매개변수가 포함된다.
RPC는 클라이언트가 자기의 프로시저를 호출하는 것처럼 원격 호스트의 프로시저를 호출할 수 있게 해준다.

3.6.3 파이프(Pipes)
파이프는 두 프로세스가 통신할 수 있게 하는 전달자로서 동작한다.
3.6.3.1 보통의 파이프
보통의 파이프는 생산자-소비자 형태로 두 프로세스 간의 통신을 허용한다. 생산자는 파이프의 한 종단에 쓰고, 소비자는 다른 종단에서 읽는다. 결과적으로 보통의 파이프는 한쪽으로만 데이터를 전송할 수 있으며 오직 단방향 통신만 가능하다. 만일 양방향 통신이 필요하다면 각각 다른 방향으로 데이터를 전송할 수 있는 두 개의 파이프를 사용해야 한다.
보통의 파이프는 파이프를 생성한 프로세스 이외에 접근할 수 없다. 따라서 통상 부모 프로세스가 파이프를 생성하고 fork()로 생성한 자식 프로세스와 통신하기 위해 사용한다.
부모, 자식 프로세스는 모두 양 종단에 대해 열려있기에 자신이 사용하지 않는 파이프의 종단을 닫아야만 한다. 그렇게 부모와 자식은 한 쪽이 쓰고 다른 한 쪽이 읽는 작업이 가능하다.
3.6.3.2 지명 파이프(Named Pipes)
지명 파이프는 좀 더 강력한 통신 도구를 제공한다. 통신은 양방향으로 가능하며 부모-자식 관계도 필요로 하지 않는다. 지명 파이프가 구축되면 여러 프로세스들이 이를 사용하여 통신할 수 있다.
Windows 시스템은 지명 파이프를 CreateNamePipe() 함수를 사용하여 생성되고 클라이언트는 ConnectNamedPipe() 함수를 사용하여 연결할 수 있다. 지명 파이프를 통한 통신을 ReadFile()과 WriteFile() 함수를 사용하여 실행한다.
3.7 요약
프로세스는 실행중인 프로그램이다. 프로세스는 실행되면서 상태를 변경한다. 각 프로세스의 상태는 새로운(new), 준비완료(ready), 실행(running), 대기(waiting), 그리고 종료(terminated) 상태 중의 하나이다. 각 프로세스는 운영체제 내에서 자신의 프로세스 제어 블록(PCB, Process Control Block)에 의해 표현된다.
프로세스가 실행되지 않을 때엔 적절한 대기 큐에 놓이게 된다. 장기 스케줄링은 CPU를 차지하기 위해 경쟁할 프로세스를 선택하는 일이다. 단기 스케줄링은 준비완료 큐로부터 하나의 프로세스를 선택하는 일이다.
운영체제는 부모 프로세스가 자식 프로세스를 생성할 수 있는 기법을 제공해야 한다. 부모는 작업을 진행하기 전에 자식 프로세스가 종료되는 것을 기다릴 수 있다. 부모와 자식이 동시에 실행 될 수 있는데 병행 실행을 허용하는 대표적 이유로는 정보 공유, 계산 속도 증가, 모듈성, 편의성 등이다.
운영체제 내에서 실행되는 프로세스들은 독립적이거나 협렬적인 프로세스다. 협렬적인 프로세스들은 서로 통신하기 위한 IPC 기법을 필요로 한다. 그것은 공유 메모리와 메시지 전달 방식이다.
공유 메모리 기법은 통신 프로세스들이 어떤 변수를 공유할 것을 필요로 한다. 이 시스템에서 통신을 제공하기 위한 책임은 응용 프로그래머가 진다.
메시지 전달 기법은 프로세스가 메시지를 교환하도록 허용하며 이 책임은 운영체제 자체에 있을 수 있다.
이 두 가지 기법은 서로 배타적이지 않으며 하나의 운영체제 내에서 두 방법이 같이 사용될 수 있다.
클라이언트 서버 시스템에서의 통신은 1) 소켓 2) 원격 프로시저 호출(RPC) 3) 파이프를 사용한다.
소켓은 통신의 극점으로 정의된 것이다. 응용 프로그램 두 개가 통신할 때 두 개의 소켓이 만들어지고 통신 채널 양단에 하나씩 배정된다
RPC는 분산 처리 통신에서 사용되는 또 다른 형태의 통신이다. RPC는 한 프로세스가 원격지 응용 프로그램의 프로시저를 호출할 때 사용한다.
보통의 파이프(익명 파이프)는 부모와 자식 프로세스 간의 통신을 허용하는 반면에 지명 파이프는 서로 무관한 프로세스 사이의 통신을 허용한다.
comments powered by Disqus