프로세스 생성 Process Creation
- 부모 프로세스가 자식 프로세스를 만든다. (프로세스는 트리 구조로 되어 있음)
- PCB에 저장된 pid (process identifier) 값으로 프로세스를 식별한다. (운영체제가 정해 준 고유 번호)
- 자원 공유 옵션 - a. 부모와 자식이 서로 모든 자원을 공유하는 옵션 b. 자식들이 부모 자원의 부분집합을 공유하는 옵션 c. 부모와 자식이 자원을 공유하지 않는 옵션
- 실행 옵션 - a. 부모와 자식이 동시에 실행하는 옵션 b. 부모가 자식이 terminate 될 때까지 기다리는 옵션
- 주소 공간 옵션 - a. 자식이 부모의 복사본인 옵션 b. 자식이 로드된 프로그램을 갖고 있는 옵션
UNIX에서의 프로세스 생성 Process Creation in UNIX
- fork 시스템 호출은 새로운 프로세스를 만들어내는 기능을 한다.
- 새로운 프로세스는 원래의 프로세스 주소 공간의 복사본을 갖고 있다.
- fork : 현재 돌아가고 있던 프로세스를 복사해서 다른 프로세스를 만든다.
- exec : 프로세스로 하여금 다른 binary를 가지고 새로 시작하도로 한다. 자식 프로세스는 exec을 통해 내용을 모두 바꾼다.
프로세스 삭제 Process Termination
- 프로세스는 마지막 statement를 실행하고 exit 시스템 호출을 이용하여 운영체제로 하여금 삭제하도록 한다.
- 부모는 자식에게서 wait 를 통해 상태 값을 받을 수 있다.
좀비 프로세스 Zombie Process
- 좀비 프로세스(혹은 defunct 프로세스)는 실행을 마쳤지만 프로세스 테이블에서 제거되지 않은 상태로 남게 된 프로세스를 뜻한다.
- 프로세스가 종료되었지만, 부모가 wait 을 통해 상태를 보고받지 못한 경우이다. (대개 버그나 코딩 에러 때문)
- 부모는 실행되고 있으나, 자식은 죽은 경우이다.
고아 프로세스 Orphan Process
- 부모가 자식 프로세스보다 먼저 종료되면 그 자식 프로세스는 고아 프로세스가 된다.
- 이때 init 프로세스가 새로운 부모가 되고, 고아 프로세스를 종료시키기 위해 wait 함수를 호출한다. (좀비 프로세스가 되는 것을 방지하기 위해)
- 부모(init 프로세스가 아닌 original one)가 죽었으나, 자식은 실행되고 있는 경우이다.
Inter-Process Communication (IPC)
- 프로세스는 독립적 혹은 서로 협력하며 동작할 수 있다. 협력하는 프로세스들은 통신하며 서로에게 영향을 미친다.
메시지 패싱 시스템 Message Passing System
- 같은 주소 공간을 사용하지 않고 서로 소통하는 프로세스들이다.
- 송신 프로세스가 정보를 받는 수신 프로세스에게 커널을 통해 정보를 전달하며, 수신 프로세스도 커널에 접근해 정보를 수신한다.
- Context switch가 발생하기 때문에 속도가 느리다.
- 커널이 기본적인 기능을 제공하므로 공유 메모리 방식에 비해선 구현이 쉽다.
- 메시지 패싱을 디자인할 때 고려해야 할 점은 다음 세 가지이다.
- 명명 Naming ; 이 프로세스에 어떤 이름을 붙여야 하는가?
- 동기화 Synchronization ; 메시지 수신과 같은 두 프로세스들이 어떻게 소통하는가?
- 버퍼링 Buffering ; 받은 정보들을 어떻게 임시적으로 저장하는가?
명명 Naming
- 통신을 원하는 프로세스들은 서로를 가리킬 수 있는 방법이 있어야 한다. 직접 혹은 간접 통신이 존재한다.
- 직접 통신을 위해서는 통신의 수신자와 송신자의 이름을 명시해야 한다.
send (P, message) - 프로세스 P에게 메시지를 전송한다.
receive (Q, message) - 프로세스 Q에게서 메시지를 수신한다.
- 통신을 원하는 두 프로세스 사이에 연결이 자동적으로 구축된다. 프로세스들은 통신하기 위해 서로 상대방의 신원(identification)만 알면 된다.
- 연결은 정확히 두 프로세스 사이에만 이루어진다.
- 통신하는 한 쌍의 프로세스 사이에는 정확하게 하나의 연결이 존재해야 한다.
- 이러한 통신은 대칭성이 두드러진다. 송신자와 수신자 모두 서로의 이름을 명시해야 한다.
- 그러나 주소 지정 시 비대칭 형식을 사용할 수도 있다. 수신자는 송신자에 대해 명시할 필요가 없다는 것이다.
send (P, message)
receive (id, message) - 임의의 프로세스들로부터 메시지를 받는다. 변수 id는 통신을 발생시킨 프로세스의 이름으로 설정된다.
- 직접 통신의 단점은 프로세스를 정확히 지정함으로써 모듈화가 제한된다는 것이다.
- 간접 통신은 메시지가 메일 박스를 통해 수송신하는 통신 방식이다.
- 각 메일박스는 고유 아이디가 있으며, 메일박스를 공유하고 있는 프로세스들만이 통신할 수 있다.
send (A, message) - 메일박스 A에 메시지를 송신한다.
receive (A, message) - 메일박스 A에게서 메시지를 수신한다.
- One-to-Many - 프로세스들이 메일박스에게서 수신할 수 있다.
- Many-to-One - 다수의 프로세스들이 하나의 수신 프로세스로 송신한다.
- Many-to-Many - 다수의 프로세스들이 다수의 수신 프로세스로 송신한다.
동기화 Synchronization
- 메시지 패싱은 봉쇄형이거나, 비봉쇄형일 수 있다. 봉쇄형은 동기식(synchronous)이며, 비봉쇄형은 비동기식(asynchronous)이다.
- 봉쇄형 송신 - 송신하는 프로세스는 메시지가 수신 프로세스 또는 메일박스에 의해 수신될 때까지 봉쇄된다.
- 비봉쇄형 송신 - 송신하는 프로세스는 메시지를 보내고 작업을 재시작한다.
- 봉쇄형 수신 - 메시지가 이용 가능할 때까지 수신 프로세스는 봉쇄된다.
- 비봉쇄형 수신 - 송신하는 프로세스는 유효한 메시지 또는 널(null)을 받는다.
버퍼링 Buffering
- 연결 안의 메시지들을 보관하고 있는 큐(queue)이다.
- 생산자-소비자 문제는 두 프로세스가 동시에 동작할 때 일어나는 이슈이다. 보통 정보가 생산되는 속도가 소비하는 속도보다 빠르기 때문에 동기화 문제가 발생하는데, 이를 해결하기 위해 생산된 데이터를 담아 두는 버퍼를 사용한다.
- Zero capacity - 큐의 최대 길이가 0이다. 즉, 연결 자체 안에 대기하는 메시지들을 가질 수 없다. 이 경우 송신자는 수신자가 메시지를 수신할 때까지 기다려야 한다. (rendezvous)
- Bounded capacity - 큐는 유한한 길이 n을 가진다. 즉, 최대 n개의 메시지가 그 안에 들어 있을 수 있다. 새로운 메시지가 전송될 때 큐가 만원이 아니라면, 메시지는 큐에 놓이며(메시지가 복사되든지 또는 메시지에 대한 포인터가 유지된다), 송신자는 대기하지 않고 실행을 계속한다. 그렇지만 연결은 유한한 용량을 가진다. 연결이 만원이면, 송신자는 큐 안에 가용한 공간이 생길 때까지 반드시 봉쇄되어야 한다.
- Unbounded capacity - 큐는 잠재적으로 무한한 길이를 가진다. 따라서 메시지들이 얼마든지 큐 안에서 대기할 수 있다. 송신자는 결코 봉쇄되지 않는다.
파이프 Ordinary Pipe
- 파이프는 한 프로세스를 다른 프로세스에 연결하는 unidirectional byte 스트림이다.
- 한쪽 방향으로만 통신이 가능하므로 읽기나 쓰기 중 하나만 가능하다. 송수신 둘 다 원하면 두 개의 파이프를 만들어야 한다.
익명 파이프 Anonymous Pipe
- 통신할 프로세스를 명확하게 알 수 있는 경우에만 통신이 가능하다. (부모-자식인 경우)
Named 파이프 Named Pipe
- 꼭 부모-자식 관계가 아니더라도 파이프를 이용해 통신할 수 있다.
- open, close, read, write과 같은 파일 명령어들로 하여금 파일처럼 처리될 수 있다.
- mkfifo 혹은 mknod 명령어로 생성된다.