프로세스 구조
프로세스는 실행 중에 프로세스 생성 시스템 호출을 이용하여 새로운 프로세스를 생성할 수 있다. 이때 프로세스 생성 순서를 저장하고 부모-자식 관계를 유지하여 계층적으로 생성한다(트리구조). 프로세스를 생성하는 프로세스를 부모 프로세스
라 하고, 생성되는 프로세스를 자식 프로세스(또는 서브 프로세스)라 한다.
대부분의 운영체제는 프로세스를 식별할 때 process id(pid) 로 구분하는데 보통 정수값이다. pid가 1인 init프로세스가 루트 부모 프로세스 역할을 수행하며, 시스템이 부팅되면 init프로세스는 다양한 사용자 프로세스를 생성한다.
보통 ps -ef 명령이나 ps aux 명령을 사용해서 현재 돌아가고 있는 프로세스를 확인할 수 있다.
프로세스 생성
시스템 콜의 fork() 함수를 호출하면 부모 프로세스는 자신과 똑같은 자식 프로세스를 생성한다. 자식 프로세스는 exec()를 통해 내용을 모두 바꾼다. fork() 함수는 부모 프로세스에겐 자식 프로세스의 pid를, 자식프로세스에겐 0을 반환한다.
부모 프로세스는 자식 프로세스와 병행하게 실행을 계속한다. 또한, 부모는 일부 또는 모든 자식이 실행을 종료할 때까지 기다린다.
프로세스 종료
프로세스가 마지막 명령의 실행을 끝내고, exit 시스템 콜을 하면 프로세스를 종료한다.
부모 프로세스는 다음 상황에서 자식 프로세스를 종료할 수 있다. 보통 부모 프로세스가 종료되면 자식 프로세스가 필요하지 않음으로 운영체제가 자식 프로세스도 종료하는데 이를 연쇄식 종료(cascading termination)라 한다.
- 자식 프로세스가 할당된 자원을 초과하여 자원을 사용할 때
- 자식 프로세스에 할당한 작업이 더는 없을 때
- UNIX에서는 exit 명령어로 프로세스를 종료하고, 부모 프로세스는 wait 명령어를 사용하여 자식 프로세스의 종료를 기다린다. wait 명령어는 종료한 자식 프로세스의 식별자를 부모 프로세스에게 돌려주며 어떤 자식 프로세스가 종료했는지 알려 준다.
자식 프로세스가 종료되었는데, 부모 프로세스가 자식 프로세스가 반환한 정보를 회수하지 않으면 자식 프로세스는 종료되었음에도 정보가 메모리에 남아 있는 좀비 프로세스가 된다.
프로세스 통신
- Independent Process(독립적인 프로세스) : 프로세스가 시스템에서 실행 중인 다른 프로세스들에게 영향을 주거나 받지 않는 경우. 다른 프로세스와 데이터를 공유하지 않는경우에 해당.
- Cooperating Process(상호 협력적인 프로세스) : 프로세스가 시스템에서 실행 중인 다른 프로세스들에게 영향을 주거나 받는 경우. 다른 프로세스와 자료를 공유하는 경우에 해당.
프로세스 협력을 허용하는데는 몇가지 이유가 있다.
- Information Sharing(정보공유) : 여러 사용자가 동일한 정보(공유 파일 등)에 흥미를 가질 수 있으므로 그러한 정보를 병행적으로 접근할 수 있도록 환경을 제공
- Computation Speed-up(계산 가속화) : 특정 task의 계산을 빠르게 하고 싶으면 그것을 subtask로 나누어 병렬로 수행되게 할 수 있다. 이 것은 여러개의 CPU 또는 I/O 채널 등 복수 개의 processing element가 있어야만 수행될 수 있다.
- Modularity(모듈성) : 시스템 기능을 별도의 프로세스들 또는 스레드들로 나누어 모듈형 시스템을 구성해야 할수도 있다.
- Convenience(편의성) : 개별 사용자들이 많은 task를 동시에 수행할 수도 있다. 이 때 병렬로 처리되도록 환경을 제공해야한다.
협력적인 프로세스들은 데이터를 교환하기 위해 프로세스 간 통신(interprocess communication, IPC) 기법이 필요하다. IPC 모델에는 공유 메모리(Shared memory)과 메시지 패싱(Message passing)이 있다.
메시지 패싱
message passing은 프로세스들 사이에 교환되는 메시지를 통해 정보를 교환한다. 송신 프로세스가 정보를 받는 수신 프로세스에게 커널을 통해 정보를 전달하며, 수신 프로세스도 커널에 접근해 정보를 수신한다. message passing은 충돌을 회피할 필요가 없기 때문에 적은 양의 데이터를 교환할 때 유용하고 구현이 쉽다. 하지만 message passing은 system call을 통해 kernel을 거쳐야하므로 시간을 좀 더 소비하게 된다.
공유 메모리
특정 메모리 공간을 두 프로세스가 함께 사용하며 정보를 주고 받는다. 이 때 프로세스들이 동시에 동일한 위치에 쓰지 않는다는 것을 보장해야 한다. 커널을 거치지 않기 때문에 속도가 빠르지만 메모리에 동시 접근하는 것을 방지하기 위해 프로그래머가 따로 구현을 해줘야 한다.
생산자-소비자 모델
협력하는 프로세스 중 정보를 생산하는 프로세스를 생산자(Producer), 정보를 소비하는 프로세스를 소비자(Consumer)라고 부른다. 생산자-소비자 문제는 두 프로세스가 동시에 동작할 때 일어나는 이슈를 말한다. 보통 정보가 생산되는 속도가 소비하는 속도보다 빠르기 때문에 동기화 문제가 발생하는데, 이를 해결하기 위해 생산된 데이터를 담아두는 버퍼(Buffer)를 사용한다. 크기에 한계가 있는 버퍼를 유한 버퍼(Bounded buffer), 버퍼의 시작과 끝을 이어붙여 크기가 무한한 버퍼를 무한 버퍼(Unbounded buffer)라고 한다.
동기화(Synchronization)
메시지 패싱의 동기화 문제를 해결하기 위해 blocking 방식과 non-blocking 방식이 사용된다.
- Blocking send: 수신자가 메시지를 받을 때까지 송신자는 block된다.
- Blocking receive: 메시지를 수신할 때까지 수신자는 block된다.
- Non-blocking send: 송신자가 메시지를 보내고 작업을 계속한다.
- None-blocking receive: 수신자가 유효한 메시지나 Null 메시지를 받는다.
'운영체제' 카테고리의 다른 글
[운영체제] CPU 스케줄링 (0) | 2021.09.06 |
---|---|
[운영체제] 스레드(Thread), 스레드 모델 (0) | 2021.09.01 |
[운영체제] 프로세스 스케줄링 (0) | 2021.08.27 |
[운영체제] 프로세스(프로세스 메모리, PCB) (0) | 2021.08.24 |
[운영체제] 컴퓨터 메모리 구조 (0) | 2021.08.23 |