1. 프로세스의 개념
실행 중인 프로그램을 의미
디스크에 존재하던 프로그램이 메모리에 올라가서 실행 되기 시작하면 프로세스가 된다. 프로세스는 CPU를 획득해 자신의 코드를 수행하기도 하고, 때로는 CPU를 반환하고 입출력 작업을 수행하기도 한다.
프로세스의 문맥(context)이란 프로세스가 현재 어떤 상태에서 수행되고 있는지 정확히 규명하기 위해 필요한 정보를 의미한다. 여러 프로세스가 실행되는 시분할 시스템 환경에서는 타이머 인터럽트에 의해 짧은 시간 동안 CPU를 사용한 후 빼앗기는 식으로 CPU 관리가 이루어진다. CPU를 다시 획득했을 때 이전의 상태를 불러오기 위해 필요한 정보가 프로세스의 문맥이다.
프로세스의 문맥은 크게 세 가지로 분류된다.
- 하드웨어 문맥 : CPU의 수행 상태를 나타낸다. PC 값과 각종 레지스터에 저장하고 있는 값들을 의미한다.
- 프로세스의 주소 공간 : 코드, 데이터, 스택으로 구성되는 프로세스 자신만의 독자적인 주소 공간
- 커널상의 문맥 : 운영체제가 프로세스를 관리하기 위해 유지하는 자료구조로 PCB와 커널스택이 이에 해당한다.
2. 프로세스의 상태
프로세스의 상태는 아래와 같이 구분된다.
- 실행(running) : 프로세스가 CPU를 보유하고, 기계어 명령을 실행하고 있는 상태
- 준비(ready) : 프로세스가 CPU만 보유하면 당장 명령을 실행할 수 있지만 CPU를 할당받지 못한 상태
- 봉쇄(blocked, wait, sleep) : CPU를 할당받더라도 당장 명령을 실행할 수 없는 프로세스의 상태. 대표적으로 프로세스가 요청한 입출력 작업이 진행 중인 경우가 있다.
- 시작(new) : 프로세스가 시작되어 그 프로세스를 위한 각종 자료구조는 생성되었지만 아직 메모리 획득을 승인받지 못한 상태
- 완료(terminated) : 프로세스가 종료되었으나 운영체제가 그 프로세스와 관련된 자료구조를 완전히 정리하지 못한 상태
위와 같이 프로세스의 상태를 구분하는 이유는 컴퓨터의 자원을 효율적으로 관리하기 위해서이다. 하나의 프로세스는 위의 상태 중 어느 한 상태에 머물러 있게 된다. 그리고 이러한 상태는 시간이 흐름에 따라 변하게 된다.
실행시킬 프로세스를 변경하기 위해 원래 수행 중이던 프로세스의 문맥을 저장하고 새로운 프로세스의 문맥을 세팅하는 과정을
문맥교환(context switch)이라고 한다. 문맥교환은 타이머 인터럽트나 프로세스의 입출력 요청 등에 의해 일어난다. 이때 준비 상태에 있는 프로세스들 중에서 CPU를 할당받을 프로세스를 선택한 후 실제로 CPU의 제어권을 넘겨받는 과정을 CPU 디스패치(dispatch)라고 한다.
3. 프로세스 제어블록(Process Control Block, PCB)
프로세스 제어블록이란 운영체제가 시스템 내의 프로세스들을 관리하기 위해 프로세스마다 유지하는 정보들을 담는 커널 내의 자료구조를 뜻한다. PCB의 구성요소는 다음과 같다.
- 프로세스의 상태(process state)
-> CPU를 할당해도 되는지 여부를 결정하기 위해 필요 - 프로그램 카운터(program counter)의 값
-> 다음에 수행할 명령의 위치를 가리킨다 - CPU 레지스터(CPU register)의 값
-> CPU 연산을 위해 현 시점에 레지스터에 어떤 값을 저장하고 있는지를 나타낸다 - CPU 스케줄링 정보(CPU scheduling information)
-> 프로세스의 CPU 스케줄링을 위해 필요한 정보 - 메모리 관리 정보(memory management information)
-> 메모리 할당을 위해 필요한 정보 - 자원 사용 정보(accounting information)
-> 사용자에게 자원 사용 요금을 계산해 청구하는 등의 용도로 사용 - 입출력 상태 정보(I/O status information)
-> 프로세스가 오픈한 파일 정보 등 프로세스의 입출력 관련 상태 정보
4. 문맥교환(Context Switch)
문맥교환이란 하나의 사용자 프로세스로부터 다른 사용자 프로세스로 CPU의 제어권이 이양되는 과정을 뜻한다.
- A 프로세스가 CPU를 할당받고 실행중에 타이머 인터럽트가 발생한다.
- CPU의 제어권은 운영체제에게 넘어간다.
- 운영체제는 타이머 인터럽트 처리루틴으로 가서 직전까지 수행 중이던 프로세스의 문맥을 저장하고 새롭게 실행시킬 B 프로세스에게 CPU를 이양한다.
- A 프로세스는 준비 상태로 바뀌고 B 프로세스는 실행 상태가 된다.
- A 프로세스는 프로그램 카운터 값 등 프로세스의 문맥을 자신의 PCB에 저장하고, B 프로세스는 예전에 저장했던 자신의 문맥을 PCB로부터 실제 하드웨어로 복원시키는 과정을 거친다.
문맥교환은 타이머 인터럽트뿐만 아니라 프로세스의 입출력 요청이나 조건 불충족으로 CPU를 휘수당하고 봉쇄 상태가 되는 경우에도 발생한다.
하지만 시스템 콜이나 인터럽트의 경우에는 프로세스의 실행모드만이 사용자모드에서 커널모드로 바뀌는 것일뿐, 문맥교환이 일어나지 않는다. 이는 다른 사용자 프로세스로 CPU의 제어권이 넘어가지 않기 때문이다. 모드 변경에 비해 문맥교환에는 훨씬 많은 오버헤드가 뒤따른다.
타이머 인터럽트가 발생하거나 프로세스가 입출력 요청 시스템 콜을 하여 봉쇄 상태에 들어가는 경우에는 문맥교환이 일어나지만, 그 밖의 인터럽트나 시스템 콜 발생 시에는 문맥교환이 일어나지 않고 실행 모드만이 변경될 뿐이다.
5. 프로세스를 스케줄링하기 위한 큐
운영체제는 준비 상태에 있는 프로세스들을 줄 세우기 위해 준비 큐(ready queue)를 두고 준비 큐의 제일 앞에 줄 서 있는 프로세스에 제일 먼저 CPU를 할당한다. 준비 큐에 프로세스들을 줄 세우는 방법은 CPU 스케줄링 방법에 따라 달라진다.
운영체제는 준비 큐 외에도 특정 자원을 기다리는 프로세스들을 줄 세우기 위해 자원별로 장치 큐(device queue)를 둔다. 위의 그림처럼 디스크 입출력 서비스가 필요한 프로세스들은 디스크 입출력 큐에 줄을 선다. 디스크 컨트롤러는 순서대로 프로세스들의 입출력 작업을 수행하고 작업이 완료되면 CPU에게 인터럽트를 발생시키게 되고, 디스크 입출력이 완료된 프로세스는 입출력 큐에서 빠져나와 CPU를 기다리는 준비 큐에 줄 서게 된다.
하드웨어 자원 외에도 소프트웨어 자원을 기다리는 경우에도 큐는 필요하다. 일관성 유지를 위해 공유 데이터는 매 시점 하나의 프로세스만이 접근할 수 있도록 해야 한다. 여러 프로세스가 공유 데이터에 동시에 접근하려고 할 경우 공유 데이터를 기다리는 큐에 줄 서게 하여 현재 그 데이터를 사용하고 있는 프로세스가 데이터를 반납하기 전까지는 접근하지 못하게 하고, 반납할 경우 큐에 줄 서 있는 순서대로 데이터의 접근 권한을 주는 방법을 사용한다.
프로세스의 상태 관리는 커널의 주소 영역 중 데이터 영역에 다양한 큐(queue)를 두어 수행하게 된다. 즉, 어떤 프로세스가 CPU를 기다리는지, 입출력을 기다리는지 등의 정보를 커널이 총체적으로 관리한다.
운영체제는 준비 큐(ready queue)와 장치 큐(device queue) 외에도 작업 큐(job queue)가 존재한다. 작업 큐는 시스템 내의 모든 프로세스를 관리하기 위한 큐로, 프로세스의 상태와 무관하게 현재 시스템 내에 있는 모든 프로세스가 작업 큐에 속하게 된다. 즉, 작업 큐에 있다고 해서 반드시 메모리를 가지고 있는 것은 아니다. 작업 큐가 가장 넓은 개념이고 준비 큐와 장치 큐에 있는 프로세스들은 모두 작업 큐에 속해 있다.
큐헤더(queue header)는 큐의 가장 앞부분을 뜻한다. 큐는 각 프로세스의 PCB를 연결 리스트 형태로 관리하며 포인터를 사용해 순서를 정한다. CPU를 할당받은 프로세스가 입출력 요청을 발생시키면 해당 장치 큐에 가서 줄을 서고 봉쇄 상태로 바뀐다. 봉쇄 상태에 있다가 해당 장치의 서비스를 받고 나서 장치 컨트롤러가 인터럽트를 발생시키면 준비 상태로 바뀌어 준비 큐로 이동하게 된다.
6. 스케줄러
어떤 프로세스에게 자원을 할당할지를 결정하는 운영체제 커널의 코드를 지칭
장기 스케줄러(long term scheduler)
- 작업 스케줄러(job scheduler)라고도 부른다.
- 어떤 프로세스를 준비 큐에 진입시킬지 결정하는 역할을 한다.
- 프로세스에게 메모리를 할당하는 문제에 관여하게 된다.
- 시작 상태의 프로세스들 중 어떠한 프로세스를 준비 큐에 삽입할 것인지 결정하는 역할을 한다.
- 가끔 호출되기 때문에 상대적으로 속도가 느린 것이 허용된다.
- 메모리에 동시에 올라가 있는 프로세스의 수를 조절하는 역할을 한다.
- 현대의 시분할 시스템 운영체제는 일반적으로 사용하지 않고 프로세스가 시작 상태가 되면 곧바로 그 프로세스에 메모리를 할당해 준비 큐에 넣어준다.
단기 스케줄러(short term scheduler)
- CPU 스케줄러라고도 부른다.
- 준비 상태의 프로세스 중에서 어떤 프로세스를 다음번에 실행 상태로 만들 것인지를 결정한다.
- 즉, 어떤 프로세스에게 CPU를 할당할 것인가를 결정한다.
- 시분할 시스템에서 타이머 인터럽트가 발생할 경우 단기 스케줄러가 호출된다.
- 매우 빈번하게 호출되기 때문에 수행 속도가 충분히 빨라야 한다.
중기 스케줄러(medium term schduler)
- 현대의 시분할 시스템 운영체제에서 장기 스케줄러 대신 중기 스케줄러를 사용한다.
- 너무 많은 프로세스에게 메모리를 할당해 시스템의 성능이 저하되는 경우 이를 해결하기 위해 메모리에 적재된 프로세스의 수를 동적으로 조절하기 위해 사용되는 스케줄러이다.
- 위의 상황에서 메모리에 올라와 있는 프로세스 중 일부를 선정해 이들로부터 메모리를 통째로 빼앗아 그 내용을 디스크의 스왑 영역에 저장해둔다.
- 즉, 프로세스당 보유 메모리양이 지나치게 적어진 경우 이를 완화시키기 위해 일부 프로세스를 메모리에서 디스크로 스왑 아웃 시키는 역할을 수행한다.
- 스왑 아웃 대상의 0순위는 봉쇄 상태에 있는 프로세스들이다. 이는 봉쇄 상태의 프로세스들은 당장 CPU를 획득할 가능성이 없기 때문이다.
- 이후에도 메모리 공간이 부족한 경우, 보통 타이머 인터럽트가 발생해 준비 큐로 이동하는 프로세스를 추가적으로 스왑 아웃시킨다. 준비 큐에 너무 많은 프로세스가 존재하면 개별 프로세스에 배정되는 메모리양이 지나치게 적어질 뿐 아니라 CPU를 한번 할당받은 후 다시 할당받기까지 오랜 시간이 소요되기 때문이다.
- 중기 스케줄러는 장기 스케줄러와 마찬가지로 메모리에 올라와 있는 프로세스의 수를 조절하는 역할을 한다.
- 중기 스케줄러의 등장으로 프로세스의 상태에 중지(suspended, stopped) 상태가 추가된다.
- 중지 상태 : 외부적인 이유로 프로세스의 수행이 정지된 상태
- 중지 상태의 프로세스는 외부에서 재개시키지 않는 이상 다시 활성화될 수 없으므로 메모리 자원이 당장 필요하지 않다.
- 따라서 메모리를 통째로 빼앗기고 디스크로 스왑 아웃된다.
- 중기 스케줄러에 의해 디스크로 스왑 아웃된 프로세스의 상태가 대표적인 중지 상태에 해당한다.
- 중지 상태는 중지준비 상태(suspended ready)와 중지봉쇄 상태(suspended block)로 세분화된다.
- 중지준비 상태 : 준비 상태에 있던 프로세스가 중기 스케줄러에 의해 디스크로 스왑 아웃된 상태
- 중지봉쇄 상태 : 봉쇄 상태에 있던 프로세스가 중기 스케줄러에 의해 디스크로 스왑 아웃된 상태
- 중지봉쇄 상태이던 프로세스가 봉쇄되었던 조건을 만족하게 되면 중지준비 상태로 바뀐다.
7. 프로세스의 생성
시스템이 부팅된 후 최초의 프로세스는 운영체제가 직접 생성하지만 그 다음부터는 이미 존재하는 프로세스가 다른 프로세스를 복제 생성하게 된다. 이때 프로세스를 생성한 프로세스를 부모 프로세스라고 하고, 새롭게 생성된 프로세스를 자식 프로세스라고 한다. 프로세스가 종료 될때는 자식 프로세스가 먼저 종료되고 해당 자식을 생성했던 부모 프로세스가 이에 대한 처리를 담당하는 방식으로 진행된다. 자신이 종료되기 위해서는 자신이 생성했던 모든 후손 프로세스들을 연쇄적으로 종료시켜야 한다.
프로세스가 자원을 획득하는 방법에는 운영체제로부터 직접 자원을 할당받는 경우, 부모 프로세스와 자원을 공유해서 사용하는 경우가 존재한다.
프로세스가 수행되는 모델에도 부모와 자식이 공존하며 수행되는 모델과 자식이 종료(terminate)될 때까지 부모가 기다리는(wait) 모델이 있다.
부모&자식 공존 모델에서는 자식과 부모가 같이 CPU를 획득하기 위해 경쟁하는 관계가 된다.
부모가 자식의 종료를 기다리는 모델에서는 자식 프로세스가 종료될 때까지 부모 프로세스는 아무 일도 하지 않고 봉쇄 상태에 머물러 있다가, 자식 프로세스가 종료되면 그때 부모 프로세스가 준비 상태가 되어 다시 CPU를 얻을 권한이 생기게 된다.
프로세스가 생성되면 자신만의 독자적인 주소 공간을 갖게 된다. 자식 프로세스는 부모 프로세스와는 별도의 주소 공간을 가지게 되는데, 처음에는 부모 프로세스의 주소 공간 내용을 그대로 복사해서 생성한다. 그 후 생성된 주소 공간 위에 새로운 프로그램의 주소 공간을 덮어씌워 실행하게 되는 것이다.
프로세스의 종료는 두 가지로 나뉜다.
※ 자발적 종료
프로세스가 마지막 명령을 수행한 후 운영체제에게 이를 알려 이루어진다. 시스템 콜을 통해 운영체제에게 자신이 종료됨을 알린다. 운영체제는 종료를 통보한 프로세스의 자원을 회수하고 시스템 내에서 해당 프로세스를 정리한다.
※ 비자발적 종료
부모 프로세스가 자식 프로세스의 수행을 강제로 종료시킨다. 강제종료가 발생하는 경우는 다음과 같다.
- 자식 프로세스가 할당 자원의 한계치를 넘어서는 많은 양의 자원을 요구할 때
- 자식 프로세스에게 할당된 작업이 더 이상 필요하지 않을 때
- 부모 프로세스가 종료(exit)되는 경우
8. 프로세스 간의 협력
프로세스는 각자 독립적인 주소 영역을 가지며 하나의 프로세스가 다른 프로세스의 주소 공간을 참조하는 것은 허용되지 않는다. 하지만, 경우에 따라서는 효율성 증대를 위해 프로세스의 협력을 허용하기도 한다.
프로세스 간의 협력 메커니즘에는 대표적으로 IPC(Inter-Process Communication : 인터프로세스 커뮤니케이션)가 있다. IPC란 하나의 컴퓨터 안에서 실행 중인 서로 다른 프로세스 간에 발생하는 통신을 말한다. 이러한 통신에서는 의사소통 기능과 함께 동기화를 보장해주어야 한다. 하나의 프로세스가 공유 데이터의 값을 변경하는 동안 다른 프로세스는 그 데이터에 접근할 수 없게 해야 한다. IPC의 대표적인 방법으로는 메시지 전달방식과 공유 메모리 방식이 있다.
메시지 전달 방식(message passing)
- 프로세스 간에 공유 데이터를 일체 사용하지 않고 메시지를 주고 받으면서 통신하는 방식
- 커널이 메시지를 전달하는 역할을 한다.
- 메시지의 전송 대상이 다른 프로세스인지 메일박스라는 저장공간인지에 따라 다시 직접통신과 간접통신으로 나뉜다.
- 직접통신 : 통신하려는 프로세스의 이름을 명시적으로 표시. 링크는 자동적으로 생성되고, 하나의 링크는 정확히 한 쌍의 프로세스에게 할당된다.
- 간접통신 : 메일박스 또는 포트로부터 전달받는다. 간접통신의 커뮤니케이션 링크는 프로세스 간에 메일박스를 공유하는 경우에만 생성된다.
공유메모리 방식(shared memory)
- 프로세스들이 주소 공간의 일부를 공유한다.
- 운영체제는 공유메모리를 사용하는 시스템 콜을 지원해, 서로 다른 프로세스들이 그들의 주소 공간 중 일부를 공유할 수 있도록 한다.
- 데이터의 일관성 문제는 커널이 책임지지 않기 때문에 프로세스들끼리 직접 공유메모리 접근에 대한 동기화 문제를 책임져야 한다.
Reference
'CS > OS' 카테고리의 다른 글
[OS] 스핀락, 뮤텍스, 세마포어 (0) | 2021.12.22 |
---|---|
[OS] 공유 자원 접근 문제 (0) | 2021.12.22 |
[OS] 04. 프로그램의 구조와 실행 (0) | 2021.12.20 |
[OS] 03. 컴퓨터 시스템의 동작 원리 (0) | 2021.12.14 |
[OS] 02. 운영체제 개요 (0) | 2021.12.13 |
댓글