프로세스는 실행되면서 상태가 변화하며, 프로세스의 상태는 현재의 활동에 따라 정의된다.
어느 한 순간에 한 processor에서는 하나의 process만이 실행된다.
따라서, 이에 많은 process가 ready, waiting 상태에 있을 수 있다.
각각의 프로세스는 자신의 종보 묶음인 PCB를 가지고 있다. PCB에는 프로세스 상태와 프로그램 카운터, 메모리 한계, 레지스터 정보 등이 담겨 있다.
프로세스를 쪼개 하나의 프로세스 안에서 동시에 여러 작업을 처리할 수 있다.
Time-sharing
방식의 목적은 각 프로그램이 실행되는 동안 user가 interact할 수 있도록 프로세스들 사이에서 CPU를 자주 switching
해주는 것이다.레디 큐에 프로세스를 옮기는 것은 잡 스케줄러, 또는 long-term 스케줄러라고 한다. 프로세스를 프로세서에 할당하는 것은 CPU 스케줄러 또는 short-term scheduler라고 한다.
프로세스들은 life-time동안 다양한 스케줄링 큐들 사이에 있게 된다.
프로세스들은 대용량 메모리에 저장되어, 실행될 때까지 기다리게 된다.
long -term Scheduler (Job Scheduler)
은 대용량 메모리에서 프로세스들을 선택하여 실행하기 위해 Memory로 load한다.
Short-term Scheduler (CPU Scheduler)
은 실행 준비가 완료된 프로세스들 중에서 선택하여, 해당 프로세스에게 CPU를 할당한다.
long-term Scheduler은 short-term Scheduler에 비해 실행 빈도수가 적은 편이다.
long-term scheduler은 degree of Multi-Programming(메모리에 있는 프로세스들의 수)를 컨트롤 한다.
Short-term Scheduler은 CPU를 위해 자주 새로운 프로세스를 선택해야 한다. (빈도수가 높다)
프로세스가 실행되다가 인터럽트가 발생해 운영체제가 개입하여 프로세서에 할당된 프로세스를 바꾸는 것을 말한다. 프로세서가 다른 프로세스로 스위치할 때, 시스템은 작업중이던 프로세스의 상태를 저장하고 새로운 프로세스의 상태를 로드한다. 컨텍스트 스위치는 오버헤드가 발생하는 작업이기 때문에 너무 자주 일어나면 성능을 저하한다.
요약 : 프로세스는 트리 구조로 이루어져 있다. 즉, 부모 프로세스가 자식 프로세스를 만든다. PCB에 저장된 pid
값으로 프로세스를 식별하는데, 이는 운영체제가 정해준 고유 번호다. 프로세스 생성은 플라나리아 번식과 유사하다. 시스템 콜의 fork()
함수를 호출하면 부모 프로세스는 자신과 똑같은 자식 프로세스를 생성한다. 자식 프로세스는 exec()
를 통해 내용을 모두 바꾼다.
실행되는 동안 프로세스는 여러 개의 새로운 프로세스를 생성할 수 있다.
생성하는 프로세스를 부모(parent)프로세스
, 새롭게 생성되는 프로세스를 자식(child)프로세스
라고 한다.
프로세스 트리
를 형성한다. UNIX, Linux와 같은 대부분의 현대 운영체제들은 프로세스 식별자 (pid)를 사용하여 프로세스를 구분한다.
pid는 보통 정수이며, 시스템의 각 프로세스에게 고유한 값을 가지도록 할당한다.
<프로세스가 새로운 프로세스를 생성할 때, 두 가지 방법!>
(1) 부모는 자식과 병행하여 실행을 계속한다. (continues to execute concurrently)
(2) 부모는 일부 또는 모든 자식이 실행을 종료할 때까지 기다린다.
새로운 프로세스들(자식 프로세스들)의 주소 공간 측면에서 볼 때 아래와 같이 두 경우로 나타날 수 있다.
(1) 자식 프로세스는 부모 프로세스의 복사본이다.
UNIX에서 새로운 프로세스는 fork()
system call을 통해 생성된다.
새로운 자식 프로세스는 부모 프로세스의 주소 공간의 복사본으로 구성된다.
기존의 부모 프로세스와 새롭게 생성된 자식 프로세스는 fork()후의 명령어에서부터 실행을 계속한다.
한 가지 차이점은 부모 프로세스는 자식 프로세스의 pid, 자식프로세스는 0이 return 된다.
(1) 자식 프로세스는 부모 프로세스의 복사본이다.
exit()
을 호출하면 프로세스를 종료시킬 수 있다. 부모 프로세스가 자식 프로세스보다 먼저 종료되면 자식 프로세스는 그 상위 프로세스를 부모 프로세스로 바라본다. 자식 프로세스가 종료되었는데, 부모 프로세스가 자식 프로세스가 반환한 정보를 회수하지 않으면 자식 프로세스는 종료되었음에도 정보가 메모리에 남아있는 좀비 프로세스가 된다.
공유 메모리는 게시판이다. 특정 메모리 공간을 두 프로세스가 함께 사용하며 정보를 주고 받는다. 커널을 거치지 않기 때문에 속도가 빠르지만 메모리에 동시 접근하는 것을 방지하기 위해 프로그래머가 따로 구현을 해줘야 한다.
메시지 패싱은 우편이다. 송신 프로세스가 정보를 받는 수신 프로세스에게 커널을 통해 정보를 전달하며, 수신 프로세스도 커널에 접근해 정보를 수신한다. 메시지 패싱은 컨텍스트 스위치가 발생하기 때문에 속도가 느리다. 다만 커널이 기본적인 기능을 제공하므로 공유 메모리 방식에 비해선 구현이 쉽다.
메시지 전달 방식은 동일한 주소 공간을 공유하지 않고도 프로세스들이 통신하고, 동기화할 수 있도록 한다. (특히 분산 시스템에서 유용함)
메시지 패싱의 동기화 문제를 해결하기 위함!
1. Blocking send: 수신자가 메시지를 받을 때까지 송신자는 block된다.
2. Non-Blocking send: 송신자가 메시지를 보내고 작업을 계속한다.
3. Blocking receive: 메시지를 수신할 때까지 수신자는 block된다.
4. Non-Blocking receive: 수신자가 유효한 메시지나 Null 메시지를 받는다.
소켓은 서버와 클라이언트가 통신하는 방식이다. IP주소와 포트 정보가 있으면 클라이언트는 네트워크를 통해 서버 프로세스에 접근할 수 있다. RPC(Remote Procedure Calls)는 프로세스와 프로세스가 네트워크로 이어져 있을 때 발생하는 호출을 말한다.
파이프는 부모 프로세스와 자식 프로세스가 통신할 때 사용하는 방식이다. 말 그대로 프로세스 사이에 파이프를 두고 정보를 주고 받는 건데, 파이프는 단방향 통신만 가능하기 때문에 양방향으로 정보를 주고 받으려면 두 개의 파이프가 필요하다. (파이프는 파일이다) 파이프에 이름을 붙인 named pipe를 사용하면 꼭 부모-자식 관계가 아니더라도 파이프를 이용해 통신할 수 있다.