CS/operating system

Process Management: 프로세스 관리 (1/3)

superbono 2021. 2. 9. 18:21

1. 프로세스의 개념

Process is a program is execution.

실행 중인 프로그램이 프로세스이다.

디스크에 존재하던 실행 파일이 메모리에 적재되고 프로그램이 CPU를 할당 받아 명령(instruction)을 실행하기 시작하면 비로소 생명력을 갖는 프로세스가 된다. 

잡(job)이라는 용어와 프로세스를 혼용해 사용하기도 한다. 프로세스를 이해하기 위해서는 프로세스 문맥(process context)에 대해 알 필요가 있다.

프로세스 문맥이란 프로세스가 현재 어떤상태에서 수행되고 있는지 정확히 규명하기 위해 필요한 정보를 의미한다. 프로세스가 시작해서 종료할 때까지 cpu에서 명령을 한꺼번에 수행하는 것이 아니라, 여러 프로세스가 cpu를 나눠쓰는 시분할 시스템 환경에서는 타이머 인터럽트에 의해 짧은 시간 cpu를 사용한 후 빼앗겼다가 추후에 다시 CPU를 획득하는 식으로 CPU 관리가 이루어진다. 따라서 CPU를 빼았겼다가 다시 획득해 명령의 수행을 재개하는 시점이 되면 이전의 CPU 보유 시기에 어느 부분까지 명령을 수행했는지 직전 수행 시점의 정확한 상태를 재현할 필요가 있다. 정확한 재현을 위해 필요한 정보가 바로 프로세스의 문맥이다. 프로세스의 문맥은 그 프로세스의 주소 공간(코드, 데이터, 스택 상태)를 비롯해 레지스터에 어떤 값을 가지고 있었는지와, 시스템 콜 등을 통해 커널에서 수행한 일의 상태, 그 프로세스에 관해 커널이 관리하고 있는 각종 정보 등을 포함하게 된다.

* CPU 수행 상태를 나타내는 하드웨어 문맥

  -program counter(pc) : cpu가 수행해야 할 메모리의 주소를 담고 있는 레지스터

  -각종 레지스터들

* 프로세스의 주소 공간 

   - code, data, stack

* 프로세스 관련 커널 자료 구조

  - PCB(Process Control Block) 

  - Kernel Stack

프로세스의 문맥을 구성하는 요소

커널 스택은 프로세스마다 갖고 있다. 프로세스의 문맥을 알기 위해선 PC가 어디를 가리키고 있느냐(즉 어디까지 실행했는지)를 알고 있어야. process의 메모리에 뭘 담고 있는가 data에 어떤 변수가 있는가 register에 뭘 담고 있는가

PCB: 인터럽트 때문에 CPU 빼앗긴 프로세스의 위치를 저장한다. 인터럽트 발생 시점에 그 프로글매 어디까지 수행했는지를 저장한다. 인터럽트 처리 후 프로세스 제어블록에 저장된 주소를 복원하여 원래 수행했던 일을 재개한다. 

 

2. 프로세스의 상태

프로세스는 상태(state)가 변경되며 수행된다. 프로세스의 상태를 구분하는 이유는 컴퓨터 자원의 효율적 관리를 위함이다.

프로세스의 상태에는 실행-running, 준비-ready, 봉쇄-(blocekd, wait, sleep)로 구분할 수 있다.

* 실행 상태

  CPU를 잡고 instrunction(기계어 명령)을 수행 중인 상태. 메모리에 여러 프로세스가 올라가 있지만 cpu는 하나뿐이므로 여러 프로세스가 동시에 수행된다고 해도 실제로 실행 상태에 있는 프로세스는 매 시점 하나뿐이다. 

* 준비 상태

 메모리에 올라와 있고 CPU만 잡으면 당장 명령을 실행할 수 있는 상태

* 봉쇄 상태

 CPU를 주어도 당장 instruction을 수행할 수 없는 상태이다. 프로세스 자신이 요청한 event(예: I/O)가 즉시 만족되지 않아 이를 기다리는 상태 또는 I/O 등의 event를 (스스로)기다리는 상태 예) 디스크에서 file 읽어와야 하는 상태

 - 시작 상태(new): 프로세스가 생성 중인 상태 자료구조는 생성 되었으나 메모리 획득 승인을 못받았음

 - 완료 상태(terminated): 수행(execution)이 끝난 상태. 종료 중인 상태 instruction이 끝났지만 정리할 게(자료구조) 남아있는 상태 

하나의 프로세스는 항상 앞서 설명한 상태 중의 어느 한 상태에 머물러 있게 된다. 그 상태는 시간이 흐름에 따라 변하게 된다(타이머 인터럽트 때문에) 타이머 인터럽트가 걸리면 CPU는 운영체제한테 넘어가고 운영체제는 타이머 인터럽트 처리 루틴으로 가서 수행 중이던 프로세스의 문맥을 저장하고 준비 상태에 있던 프로세스 중에서 새롭게 CPU 제어권을 부여할 프로세스를 선택한다. 이 때 준비 상태에 있는 프로세스 중에서 CPU를 할당받을 프로세스를 선택한 수 실제로 CPU의 제워권을 넘겨받는 과정을 CPU 디스패치(CPU dispatch)라고 한다. 그러면 원래 수행중이던 프로세스는 준비 상태로 변하고 새롭게 할당 받은 프로세스가 실행 상태가 된다. 예시는 타이머 인터럽트가 발생하는 경우 외에도 I/O 요청 등으로 실행 상태에서 봉쇄상태로 바뀌는 경우들을 들 수 있다.

 

<프로세스의 상태> 큐들은 전부 커널 주소공간의 데이터 영역에 있는 자료구조들이다.

디스크 파일 i/o를 통해서 프로세스의 상태를 알아보자. 사용자 프로세스가 명령을 수행하다가 파일 i/o 명령을 받으면 이건 특권 명령이기 때문에 사용자 프로세스가 할 수 없다. 따라서 시스템 콜을 하게 되고 cpu는 인터럽트 라인을 체크하고 mode bit를 0으로 바꾸고 cpu는 운영체제가 제어권을 잡게 된다. 그 후 디스크 컨트롤러에 파일을 읽어오란 명령을 내리고 디스크 컨트롤러는 디스크에서 파일을 읽어다가 로컬 버퍼에 저장한다. 한편 i/o는 시간이 오래 걸리기 때문에 동기식 입출력의 2번째 구현 방법인 i/o 요청한 프로세스는 잠시 blocked 상태로 바꾸고 cpu dispatch를 통해 cpu waiting 상태이던 다른 프로세스가 cpu를 할당받는다. 준비 상태인 프로세스는 cpu만 획득하면 곧바로 명령을 수행할 수 있으므로 cpu를 할당받은 새로운 프로세스는 실행 상태로 변경되어 자신의 코드를 cpu에서 실행하게 된다. 한편 i/o를 요청한 프로세스는 디스크 입출력을 기다리는 큐에 줄 서 있다가 자기 차례가 되어 디스크 컨트롤러로부터 서비스를 받고 나면(디스크 컨트롤러가 로컬 버퍼에 전부 읽어오면) 디스크 컨트롤러가 cpu에게 인터럽트를 발생시켜 작업이 완료되었음을 알린다. 그럼 다른 프로세스를 실행하던 cpu는 다시 mode bit 0 수행되고 있던 프로세스는 사용자 모드에서 커널모드, cpu 제어권은 운영체제에게 넘어가서 운영체제는 메모리에 로컬버퍼의 내용을 복사해온다.  이 인터럽트는 blocked 상태에 있던 i/o 요청한 프로세스를 waiting 상태로 바꾸어서 cpu를 얻기 기다리는 ready queue에 줄서게 된다. 인터럽트 처리 루틴 이전에 수행되던 프로세스에게 cpu를 다시 주고 그 프로세스의 직전 수행 시점 이후의 코드를 실행하지만 경우에 따라서는 인터럽트 당한 프로세스에게 cpu를 다시 할당하지 않고 i/o 요청한 프로세스가 더 우선순위가 높은 프로세스일 경우 문맥교환을 통해서 cpu 제어권을 이양시킬 수 있다. 즉 인터럽트 발생 전에 수행되던 프로세스가 아니라 방금 입출력을 끝낸 프로세스에게 cpu를 할당하는 경우도 있다는 것이다. 

 

3. 프로세스 제어 블록

Process Control Block

PCB(Process Control Block) 프로세스 제어 블록이란 운영체제가 각 프로세스를 관리하기 위해 프로세스 당 유지하는 정보이다.

다음의 구성 요소를 가진다.(구조체로 유지됨)

  1. OS가 관리상 사용하는 정보

    - process state(CPU를 할당해도 되는지 여부), process ID

    - scheduling information, priority

  2. CPU 수행 관련 하드웨어 값

    - program counter (다음에 수행할 명령의 위치)

    - registers (cpu의 연산을 위해 현 시점 레지스터에 어떤 값을 저장하고 있는지)

 3. 메모리 관련

    - code, data, stack의 위치 정보

 4. 파일 관련

   - open the file desciptors...

cpu 스케줄링 정보, 메모리 관련 정보 -> 프로세스의 cpu 스케줄링과 메모리 할당을 위해 필요한 정보

 

4. 문맥 교환

문맥교환이란?

문맥을 저장하고 새로운 프로세스의 문맥을 세팅하는 과정이다. 하나의 사용자 프로세스에서 다른 프로세스로 넘겨주는 과정이다. cpu가 다른 운영체제에게 넘어갈 때 운영체제는 다음을 수행한다. cpu를 내어주는 프로세스의 상태를 그 프로세스의 pcb에 저장하고 cpu는 새롭게 얻는 프로세스의 상태를 pcb에서 읽어온다.

문맥 교환(context swtich)

사용자 프로세스가 cpu를 할당 받고 실행되던 중에 타이머 인터럽트가 발생하면 cpu의 제어권은 운영체제에게 넘어가게 된다. 그러면 운영체제는 타이머 인터럽트 처리루틴으로 가서 직전까지 수행 중이던 프로세스의 문맥으로 가서 새로이 실행시킬 프로세스에게 cpu를 이양시킨다. 이 상태에서 실행 중이던 프로세스는 준비 상태로 바뀌고 새롭게 cpu를 할당받은 프로세스는 실행 상태가 된다. 문맥교환 중에 원래 cpu를 보유하고 있던 프로세스는 어디까지 실행했는지를 알려주는 프로그램 카운터값 등을 해당 프로세스의 pcb에 저장하고 새로이 cpu를 할당받은 프로세스는 자신의 pcb에서 어디까지 실행했는지를 꺼내와서 복원시킨다. 이건 타이머 인터럽트가 걸렸을 때 예이지만, i/o 나 다른 조건을 충족하지 못해 cpu가 회수 당하고 blocked 상태가 되는 경우에도 발생할 수 있다. 

프로세스가 i/o 요청 등 특권 명령을 요청하면서 시스템 콜을 하면 cpu 제어권이 운영체제로 넘어가고 운영체제 커널의 코드가 실행된다. 이 경우에도 사용자 프로세스의 문맥을 해당 프로세스의 pcb에 저장하게 되지만, 이것을 문맥교환이라고 하지는 않는다. 이 경우는 하나의 프로세스 모드가 사용자 모드 - 커널 모드 - 사용자 모드로 변환되는 과정일 뿐 다른 프로세스에게 cpu가 넘어가는 것이 아니기 때문이다. 전 포스팅에서 모트 비트가 0으로 바뀌며 cpu가 운영체제에게 넘어가서 커널의 코드가 실행이 되더라도 운영체제가 실행 중이다라고 말하지 않고 사용자 프로세스가 커널모드로 실행중이다고 말했는데 이것과 같은 맥락이라고 보면 된다. 이와 같은 모드 변경과 달리 문맥 교환에는 훨씬 많은 오버헤드(overhead)가 발생한다. 따라서 cpu에게 할당 시간을 아주 작게 세팅해 타이머 인터럽트가 빈번하게 발생하고, 프로세스 간 문맥교환이 빈번하게 발생하도록 하면 이에 드는 오버헤드가 커진다. 이와 반대로 할당 시간을 길게 세팅하면 운영체제의 시불할 시스템 의미가 퇴색하게 되므로(시간을 쪼개서 프로세스마다 돌아가면서 수행하게끔 함) 적절한 cpu 할당시간을 정하는 것이 중요하다.