[OS] Process

impala·2023년 3월 13일
0

[CS] Operating System

목록 보기
3/4

3. 프로세스

3.1 프로세스 구성요소

프로세스란 컴퓨터에서 현재 수행중인 프로그램을 의미하는 개념으로, 프로그램이 수행되기 위한 여러 정보들로 구성되어 있다.
가장 먼저 프로세스는 실행될 프로그램의 코드와 프로그램에 필요한 데이터를 가지고 있어야 한다. 또한 프로세서가 프로그램을 수행하기 위해서는 식별자와 상태 등 여러 문맥정보가 필요한데, 프로세스는 이 정보들을 프로세스 제어블록(Process Control Block, PCB)라는 자료구조에 담아 관리한다.
PCB에는 다음과 같은 정보들이 저장된다

  • 식별자
  • 프로세스의 상태
  • PC(Program Counter)
  • 메모리 포인터 : 프로그램 코드, 데이터등의 메모리상의 주소
  • Context data
  • I/O state : 프로세스에 할당된 I/O장치, 및 이벤트 정보
  • Accounting information : 리소스 사용률 등의 모니터링 정보

정리하자면 프로세스를 구성하는 요소는 프로그램 코드 및 데이터와 PCB라고 볼 수 있다.

3.2 프로세스 상태

하나의 프로그램을 수행하기 위해서는 그 프로그램에 대한 프로세스가 생성되고 운영체제에 의해 관리되고, 운영체제는 프로세스에게 프로세서를 할당하여 명령어가 수행될 수 있도록 한다.
여러 프로세스가 동시에 수행되고 있는 상황이라면 운영체제 중 프로세서의 제어권을 한 프로세스에서 다른 프로세스로 넘겨주는 디스패쳐라는 프로그램을 통해 일정 시간마다 프로세스가 교체되면서 수행된다. 이 과정을 자세히 보면 아래 그림과 같다.

쉽게 정리하자면 각 프로세스는 정해진 시간만큼 프로세서를 사용할 수 있고, 시간이 만료되면 인터럽트가 발생하여 디스패쳐 루틴이 실행되고, 다른 프로세스가 프로세서를 사용할 수 있게 된다. 이렇게 여러 프로세스가 번갈아 수행되는 것을 인터리빙(Interleaving)이라 한다.

운영체제는 프로세스를 관리하기 위해 어느 프로세스가 수행될지 결정하고 각 프로세스에게 필요한 자원을 할당해주는 역할을 담당하는데, 이를 위해서는 프로세스의 상태를 정의해야 한다.

프로세스 생성, 종료

프로세스의 상태를 정의하기 전에 모든 프로세스의 라이프사이클은 생성(creation)으로 시작되어 종료(termination)로 끝난다.

  • 프로세스 생성 : 새로운 프로세스가 생성되기 위해서 운영체제는 프로세스 자료구조를 만들고 메모리공간을 할당한다. 이 과정을 통해 생성된 프로세스는 New상태를 가진다. 프로세스가 생성되는 이벤트는 다음과 같다.

    • 새로운 배치 작업 제출
    • 사용자가 터미널에 로그온
    • 운영체제의 서비스제공 : 사용자 프포그램에서 I/O작업을 요청하는등의 경우 운영체제가 관련된 서비스의 프로세스를 생성한다.
    • 프로세스 스폰(Process Spawn) : 하나의 프로세스가 다른 프로세스를 생성하도록 운영체제에게 요청하는 경우. 이때, 스폰을 요청한 프로세스는 부모 프로세스, 스폰당한 프로세스는 자식 프로세스라 한다.
  • 프로세스 종료 : 프로세스가 아래의 이유들로 중단(abort)되거나 중지(halt)되면 해당 프로세스는 수행가능 프로세스 풀에서 방출되고 프로세스의 정보는 유틸리티 프로그램에 의해 기록된 후 삭제된다. 이 단계의 프로세스는 Exit상태를 가진다.

    • 정상 완료
    • 오류 및 결함
    • 부모 프로세스의 요청 혹은 부모 프로세스 종료

2-state process model

프로세스의 상태를 기술하는 가장 간단한 분류로는 특정시점의 프로세스가 실행중인지 그렇지 않은지로 나누는 것이다. 즉, 프로세스는 특정 시점에 Running 과 Not Running 둘중 하나의 상태를 가지고 있다고 볼 수 있다. 이렇게 프로세스를 2가지 상태로 나누어 설명하는 모델을 2-state process model이라 한다.

이 모델에서 운영체제는 새로운 프로세스를 생성할 때 PCB를 만들고 Not Running상태로 초기화한다. 이후 Running상태에 있던 프로세스가 인터럽트당하면 디스패쳐가 다음으로 수행될 Not Running상태의 프로세스를 고른다. 이 과정에서 Running상태에 있던 프로세스는 Not Running상태로 업데이트되고, 디스패쳐에 의해 선택된 프로세스는 Running상태가 된다. 이때, 디스패쳐는 프로세스 큐를 운영하여 다음으로 수행될 프로세스를 고르는 방식으로 구현될 수 있다.

이 모델에서 중요한 점은 모든 프로세스는 운영체제에 의해 관리되기 때문에 각 프로세스는 운영체제에게 자신의 상태를 알려야 할 의무가 있는데, 이를 담당하는 것이 바로 PCB이다.

5-state process model

위의 2-state model은 모든 프로세스들이 항상 수행할 준비가 되어있는 경우 효과적이다. 하지만 한 프로세스가 I/O작업등의 이벤트를 기다리고 있는 상황이라면 프로세서가 할당되어도 즉시 처리되지 못하는 프로세스에게 프로세서가 할당되는 경우가 발생한다. 이런 문제를 해결하기 위해 5-state model에서는 Not Running상태를 프로세서가 할당되면 즉시 수행될 수 있는 Ready상태와 외부 이벤트를 기다리고 있는 Blocked(Waiting)상태로 구분한다.

이 모델에서는 New, Exit, Blocked상태를 추가하여 프로세스의 동작을 설명한다. 가장 큰 특징은 다음과 같다.

  • New -> Ready : 프로세스의 생성과 준비상태를 분할하여, 운영체제가 새로 생성된 프로세스를 수용할 준비가 되면 Ready상태로 바꾸고 프로세스를 메모리에 올린다.
  • Running -> Ready : 주로 프로세스에게 할당된 시간이 지나 다음 프로세스로 넘어가는 경우나 우선순위가 높은 프로세스가 Blocked상태에서 Ready상태가 되면 실행중이던 프로세스가 인터럽트 당해 제어권을 운영체제에게 빼앗기는 경우 발생한다. 두번째 경우처럼 프로세스가 리소스의 사용을 마치기 전에 반납을 요구하는 것을 Preemption이라 한다.
  • Running -> Blocked : 수행중이던 프로그램이 운영체제에게 리소스를 요청하였는데 즉시 할당할 수 없어 기다려야 하는 경우 발생한다.
  • Blocked -> Ready : 프로세스가 기다리던 이벤트가 발생하면 Ready상태로 바뀐다.

이를 구현하기 위해서 운영체제는 여러개의 큐를 운영하는 방법을 사용할 수 있다.

첫번째는 Ready상태의 프로세스를 Ready queue에, Blocked상태의 프로세스를 Blocked queue에 관리하는 방법이 있다. 이 경우 운영체제는 특정 이벤트가 발생하면 Blocked queue를 모두 탐색하여 그 이벤트를 기다리고 있던 프로세스를 찾아 Ready queue에 올린다.

두번째는 각 이벤트마다 큐를 운영하는 방법이다. 이 방법은 특정 이벤트가 발생하면 운영체제는 탐색과정 없이 그 이벤트의 큐에서 대기중인 모든 프로세스를 Ready queue로 올린다.
마지막으로 프로세스마다 우선순위가 부여된 경우 우선순위 레벨 당 하나의 Ready queue를 운영하는 방법이 있다.

suspended process

5-state model만으로도 운영체제를 구축할 수 있지만 좀 더 복잡한 상황에서 효율성을 높이기 위해 새로운 상태를 추가시켜야 할 필요가 있다.

가상메모리를 사용하지 않는 시스템을 가정했을 때, 프로세스가 실행되기 위해서는 그 프로세스의 전체가 주기억장치에 올라와있어야 한다. 따라서 Ready queue나 Blocked queue에 있는 모든 프로세스는 주기억장치에 상주해야 한다. 이때, 프로세서는 Ready queue에 있는 프로세스를 Round robin방식으로 순차적으로 실행하고 I/O를 요청하는 프로세스를 Blocked queue로 보내는데, 일반적으로 프로세서의 처리속도가 I/O작업보다 훨씬 빠르기 때문에 메모리에 올라와있는 대부분의 프로세스들은 Blocked queue에서 대기하게 되고 결과적으로 프로세서는 대부분의 시간을 idle상태로 있게된다.

이러한 문제를 해결하기 위한 간단한 방법으로는 주기억장치의 용량을 확장하는 것인데, 이 방법은 비용이 추가되고 메모리 용량이 증가함에 따라 프로세스의 크기도 커지기 때문에 근본적인 해결책이라고 볼 수 없다. 따라서 이 문제를 해결하기 위해서 등장한 것이 바로 Swapping이다.

Swapping이란 주기억장치에 올라와있는 프로세스 중 Ready queue에 있는 것이 하나도 없다면(모든 프로세스가 Blocked상태라면) 프로세스중 하나를 디스크로 내려 Suspended queue에 추가하고 Suspend라는 새로운 상태로 업데이트한다. 이 과정을 통해 주기억장치에 생긴 빈 공간에 새로운 프로세스를 올려 프로세서가 작업을 진행할 수 있도록 한다. 이때 주기억장치에 올리는 새로운 프로세스는 Suspended queue에서 선택한다.

그런데 만약 주기억장치에 새로 올린 프로세스가 여전히 Blocked상태라면 효과가 없기 때문에 Suspend상태를 두 종류로 나누어 관리한다. 따라서 이 모델에서 Not Running상태의 프로세스는 아래와 같이 총 4개의 상태로 분할된다.

  • Ready : 프로세스가 주기억장치에 있고, 즉시 수행될 수 있음
  • Blocked : 프로세스가 주기억장치에 있지만, 이벤트를 기다리고 있음
  • Ready/Suspend : 프로세스가 디스크에 있지만. 주기억장치에 올라가면 즉시 수행될 수 있음
  • Bloceked/Suspend : 프로세스가 디스크에 있고, 이벤트를 기다리고 있음

즉, Swapping을 통해 주기억장치에서 디스크로 내려가는 프로세스들은 Blocked/Suspend상태가 되고, 디스크에서 주기억장치로 올라가는 프로세스는 Ready/Suspend상태의 프로세스 중에서 선택한다.

위의 그림에서 추가된 특징은 다음과 같다.

  • Blocked -> Blocked/Suspend : Ready상태의 프로세스가 하나도 없거나 주기억장치에 공간이 부족하면 Blocked상태의 프로세스를 디스크로 Swap out한다.
  • Blocked/Suspend -> Ready/Suspend : Blocked/Suspend상태의 프로세스가 기다리고있던 이벤트가 발생한 경우
  • Ready/Suspend -> Ready : 주기억장치에 Ready상태의 프로세스가 없거나 우선순위가 더 높은 프로세스가 Ready/Suspend상태에 있는 경우
  • Ready -> Ready/Suspend : 주기억장치에 Ready상태의 프로세스만 있지만 더 많은 공간이 필요한 경우 Ready상태의 프로세스를 디스크로 내릴 수 있다.
  • New -> Ready/Suspend : 일반적으로 프로세스가 생성되면 Ready상태가 되어 주기억장치에 올리지만, 주기억장치에 공간이 부족한 경우 Ready/Suspend상태로 설정하여 디스크에 보관할 수 있다.
  • Blocked/Suspend -> Blocked : 우선순위가 높은 프로세스가 Blocked/Suspend상태에 있고 이벤트가 곧 발생할 것이라고 예상되는 경우
  • Running -> Ready/Suspend : Blocked/Suspend상태에 있는 우선순위가 더 높은 프로세스의 이벤트가 발생한 경우 Running상태의 프로세스를 바로 디스크로 내려(Preemption) 주기억장치에 공간을 마련한다.

3.3 프로세스 구조

운영체제 자료구조

운영체제는 프로세스와 시스템 자원을 관리하는 개체이다. 이를 위해서 운영체제는 각각의 상태를 유지하는 테이블을 가지고 있다.

  • 메모리 테이블 : 주기억장치와 보조기억장치의 track정보를 유지. 프로세스에게 할당된 주기억장치 및 디스크 주소 및 각각에 대한 접근권한등을 포함한다.
  • I/O 테이블 : 특정 시점에 I/O장치의 상태(이용가능 or 프로세스에게 할당), I/O작업의 진행상태, I/O작업을 위한 메모리상의 출발지 및 목적지주소를 포함한다.
  • 파일 테이블 : 파일의 존재여부, 디스크상의 위치, 속성등을 포함한다.
  • 프로세스 테이블 : 프로세스를 관리하기 위한 정보(프로세스 이미지)를 유지하는 테이블. 위의 세가지 테이블은 프로세스를 위해 관리되는 것이기 때문에 프로세스 테이블과 직/간접적으로 참조된다.

프로세스 이미지(Process Image)

물리적으로 프로세스는 프로세스 이미지라는 자료구조를 통해 표현된다. 프로세스 이미지는 프로그램의 코드, 데이터, 시스템 스택, 프로세스 제어블럭으로 이루어져있는데, 각각의 특징은 다음과 같다.

  • 사용자 프로그램 : 수행 될 프로그램
  • 사용자 데이터 : 프로그램에 사용될 데이터
  • 시스템 스택 : 프로시저 및 매개변수를 보관하는데 사용되는 스택
  • 프로세스 제어블록 : 운영체제가 프로세스를 제어하기 위한 속성값들의 집합

현대 운영체제는 가상 메모리의 페이징 기술을 통해 프로세스 이미지의 일부분만 주기억장치에 올려 실행하고 나머지부분은 보조기억장치에 보관해둘 수 있다. 따라서 운영체제가 관리하는 프로세스 테이블에는 각 프로세스 이미지에 대한 페이지들의 위치정보가 포함되어야 한다. 즉, 프로세스 테이블은 위의 그림과 같이 프로세스 이미지에 대한 포인터를 통해 프로세스의 위치정보를 관리하는 테이블이라고 볼 수 있다.

프로세스 제어블록(Process Control Block)

프로세스 제어블록이란 운영체제가 프로세스를 관리하기 위해 필요한 속성정보들의 집합으로, 프로세스 식별자, 프로세서 상태정보, 프로세스 제어정보를 포함한다.

  • 프로세스 식별자(Process Identification) : 운영체제가 각 프로세스에게 부여하는 유일한 식별자로 주 프로세스 테이블에 대한 인덱스를 저장한다. 식별자에는 다음과 같은 항목이 포함된다.
    • PID : Process ID
    • PPID : Parent Process ID
    • UID : User ID
  • 프로세서 상태정보(Proceseor State Information) : 프로세스가 실행되는 동안 프로세서의 레지스터에 저장되는 정보로 프로세스의 수행이 재개될 때 수행 문맥을 복구하기 위해 저장된다. 상태정보에는 다음과 같은 항목이 포함된다.
    • User-visible 레지스터 : 사용자 모드에서 사용가능한 레지스터
    • Control & State 레지스터 : PC, condition code, PSW(Program State Word)
    • 스택 포인터
  • 프로세스 제어정보(Process Control Information) : 운영체제가 프로세스를 관리하기 위한 추가정보가 저장된다. 제어정보에는 다음과 같은 항목이 포함된다.
    • 스케줄링 및 상태정보 : 프로세스 상태(Ready, Blocked, Suspend 등), 우선순위, 이벤트, 스케줄링 정보
    • 자료구조 : 다른 프로세스를 가리키는 포인터 정보. Ready queue, Blocked queue등을 표현할 때 사용한다.
    • IPC(Inter Process Communication) : 프로세스간 통신을 위한 정보
    • 프로세스 권한(Process Privileges)
    • 메모리 정보 : 프로세스에 할당된 가상메모리의 세그먼트, 페이지 테이블의 포인터
    • 리소스 소유권 및 이용률 정보

프로세스 제어블록은 운영체제가 프로세스를 관리하기 위한 모든 정보가 담겨있는 자료구조이기 때문에 스케줄링, 인터럽트등을 포함한 운영체제의 모든 모듈에 의해 참조될 수 있다. 운영체제의 모든 루틴들은 프로세스의 ID를 통해 프로세스를 직접 참조할 수 있는데, 운영체제의 루틴이 프로세스를 직접 참조하도록 운영체제를 설계한다면 단일 루틴의 버그가 PCB에 손상을 줄 수도 있고, PCB의 설계가 변경되면 많은 운영체제 모듈이 영향을 받을 수 있다. 그렇기 때문에 운영체제는 모든 루틴들이 PCB에 접근할때 핸들러(Handler) 루틴을 통해 접근하도록 한다. 즉, 핸들러 루틴은 PCB에 대한 인터페이스 역할을 함으로써 운영체제의 여러 루틴으로부터 PCB를 보호할 수 있다.

3.4 프로세스 컨트롤

프로세스 생성

운영체제가 프로세스를 생성하는 구체적인 과정은 다음과 같다.

  1. 새로운 프로세스에 식별자를 부여하고 프로세스 테이블에 이를 등록한다.
  2. 프로세스 이미지를 저장하기 위한 공간을 할당한다.
  3. PCB를 초기화한다. 이때 초기화되는 정보는 식별자(PID, PPID, UID), 프로그램 카운터(프로그램 진입점), 시스템 스택 포인터, 프로세스 상태 등(주로 Ready, Ready/Suspend)이 포함된다.
  4. 프로세스들을 연결한다(Ready queue, Blocked queue등에 추가)
  5. 프로세스의 정보로 다른 자료구조를 초기화한다.(billing, account등)

모드 스위칭

대부분의 프로세서는 사용자 프로그램을 실행시키는 User mode와 그보다 높은 권한을 가진 운영체제를 실행시키는 Kernel mode를 지원한다. 프로세서가 두가지 실행모드를 지원하는 이유는 사용자 프로그램으로부터 운영체제와 주요 운영체제 제어 테이블들을 보호하기 위함이다. 현재 프로세서에서 실행중인 명령이 어느 모드인지를 확인하기 위해서는 PSW의 한 비트를 사용하여 유저모드와 커널모드를 나타낸다. 또한 모드의 변경은 사용자 프로그램에서 운영체제 서비스를 호출하거나 인터럽트를 통해 운영체제의 루틴이 실행될 때 커널모드로 변경되고, 운영체제의 루틴이 끝나고 사용자 프로그램으로 제어가 돌아갈 때 사용자 모드로 변경된다.

사용자 프로그램으로부터 운영체제로 제어가 넘어오는 경우 모드 스위칭이 발생하는데, 이 경우 운영체제의 동작과정은 다음과 같다.

  1. PC의 값을 인터럽트 핸들러의 시작주소로 설정한다
  2. 사용자 모드를 커널모드로 전환시켜 인터럽트 핸들러가 privileged instruction을 수행할 수 있도록 설정한다.

이 과정에서 수행중이던 프로세스의 문맥정보(프로세서 레지스터에 저장된 값)는 PCB에 저장된다.

프로세스 스위칭

프로세스의 교환은 실행중인 프로세스로부터 운영체제로 제어가 넘어올 때마다 발생한다. 운영체제가 제어권을 갖게 되는 경우는 다음과 같다.

  • 인터럽트 : 현재 명령어의 외부에서 비동기적인 외부사건에 의해 발생한다. 인터럽트가 발생하면 인터럽트 핸들러로 제어가 넘어가 기본적인 작업을 처리한 후 인터럽트의 종류에 맞는 루틴으로 넘어간다.
    • 클럭 인터럽트 : 현재 수행중인 프로세스에게 할당된 최대 시간을 모두 사용한 경우 다음 프로세스로 디스패치된다.
    • I/O 인터럽트 : 발생한 I/O작업의 종류에 따라 Blocked queue에 있는 프로세스를 Ready상태로 업데이트한다.
    • Memory fault : 프로세서가 주기억장치에 없는 데이터를 참조하는 경우 보조기억장치로부터 데이터를 주기억장치에 가져오기 위해 프로세스를 Blocked상태로 바꾸고 다음 프로세스로 디스패치한다.
  • 트랩 : 인터럽트의 한 종류지만 현재 명령어 내부에서 생긴 오류나 예외에 의해 발생한다. 시스템에 가해지는 위험정도에 따라 프로세스를 종료하거나 복구 프로시저를 수행한다.
  • 관리자 호출 : 사용자 프로그램에 의해 명시적으로 운영체제의 기능을 호출하는 경우 발생한다. 사용자 프로세스는 Blocked상태로 바뀌고 사용자가 요청한 운영체제의 루틴으로 제어가 넘어간다

위와 같은 경우에 의해 프로세스가 변경되는 경우 운영체제의 동작과정은 다음과 같다.

  1. PC및 다른 레지스터들을 PCB에 저장한다.
  2. 현재 프로세스의 PCB를 갱신한다.(프로세스 상태 변경 등)
  3. 현재 프로세스의 PCB를 적절한 큐(Ready queue, Blocked queue, Suspended queue등)로 옮긴다.
  4. 스케줄러에 의해 다음으로 수행될 프로세스를 선택한다.
  5. 선택된 프로세스의 PCB를 갱신한다. 이때 프로세스의 상태는 Running으로 바뀐다.
  6. 선택된 프로세스의 문맥을 복원한다(레지스터 값 복원)

모드 스위칭은 현재 프로세스의 상태에 변화가 없기 때문에 오버헤드가 크지 않지만, 프로세스 스위칭의 경우 프로세스의 상태를 변경하기 때문에 여러 값들이 변하므로 오버헤드가 크다.

3.5 운영체제 프로세스

운영체제도 결국 프로그램의 집합이기 때문에 프로세서에게 의존한다는 특징이 있다. 따라서 운영체제도 하나의 프로세스라고 볼 수 있는데, 운영체제 프로세스를 보는 관점에 따라 다양한 운영체제를 설계할 수 있다.

비 프로세스 커널(Nonprocess Kernel)

전통적이고 일반적인 방법으로 모든 프로세스의 외부에서 운영체제 커널이 동작하는 방법이다. 프로세스가 인터럽트 당하거나 관리자 호출이 발생하면 문맥이 저장되고 커널로 제어권이 넘어간다. 운영체제는 독립된 메모리 공간과 시스템 스택을 가지고 커널모드에서만 동작한다. 여기에서 프로세스의 개념은 사용자 프로그램에만 적용된다.

사용자 프로세스 내부 OS(Execution within User Processes)

사용자 프로세스 내에서 운영체제 기능이 동작하는 방법이다. 각 프로세스 이미지에는 커널 프로그램 코드와 데이터, 커널의 동작을 위한 시스템 스택이 포함된다. 인터럽트등에 의해 운영체제로 제어가 넘어가는 경우 프로세스의 문맥정보가 저장되고 운영체제 루틴으로 모드 스위칭이 발생하지만 프로세스 교환은 발생하지 않는다. 이후 같은 프로세스가 실행되어야 한다면 단순히 모드 스위칭만 발생한다. 만약 다른 프로세스가 실행된다면 프로세스 외부에 있는 프로세스 교환 루틴에 의해 제어가 다른 프로세스로 넘어간다. 이 방식의 장점은 인터럽트 이후 같은 프로세스가 실행될 때 오버헤드가 큰 프로세스 스위칭 과정이 발생하지 않는다는 점이다.

프로세스 기반 OS(Process-Based OS)

운영체제를 프로세스들의 집합으로 구현하는 방법이다. 커널의 주요 기능들은 여러개의 프로세스로 구성된다. 프로세스가 교환될 때에는 프로세스 외부의 프로세스 교환 루틴에 의해 제어가 다른 프로세스로 넘어간다. 이 방식의 장점은 운영체제를 모듈화함으로써 설계원칙을 지킬 수 있고, 멀티프로세서나 멀티 컴퓨터 환경에서 성능을 향상시킬 수 있다는 점이다.

참고자료

  • Operating Systems : Internas and Design Principles - William Stallings

2개의 댓글

comment-user-thumbnail
2024년 3월 27일

유저 스택과 시스템 스택이 같은것인가요? 사진상에서는 유저스택만 포함되어있고 시스템 스택에 대한 이야기는 없는데 왜 그런건지 궁금합니다

답글 달기
comment-user-thumbnail
약 5시간 전

준비 Geometry Dash 상태 (Ready State): 프로세스가 CPU를 할당받기를 기다리는 상태입니다. 이 때 CPU가 할당되기를 기다리며 다른 프로세스들과 경쟁합니다.

답글 달기