Hyokyun Yim bio photo

Hyokyun Yim

Koreatech Computer Science Engineering undergraduate 4 grade.

Facebook Github

Process의 개념과 스케줄러, 디스패처, Context Switching 에 대해 알아보자

Overview

프로세스 개념

  • 프로세스는 State(Context)와 Execution stream(Thread of control) 로 구성되어있다.
  • 프로세스는 OS 위에서 프로그램을 실행시키는 기본 주체(Runtime 시스템의 수행 주체: CPU나 여러 자원을 할당받는 주체)이다.
  • OS에서 가장 중요한 단위
  • 컴퓨터 시스템의 많은 일들을 잘 쪼개서 정리(Decomposition)하는 작업을 하는 Unit이 프로세스이다.
  • 프로세스는 한마디로 정의하면 수행중인 프로그램이다. 좀 더 구체화 하면 특정 프로세스 상태 위에서 수행되는 실행 흐름이다.
  • 프로그램과 프로세스는 어떠한 차이점이 있을까? 프로그램은 저장매체에 저장된 수동적인 코드 시퀀스(0101 로 구성된)이다. 우리가 게임cd를 컴퓨터에 넣고 바탕화면에서 실행시키면 프로그램에 CPU를 할당하고 실행 시킨다. 그것이 프로세스이다.
  • 즉 프로그램 일 때는 저장매체만 점유 했지만 프로세스가 되면 CPU, Memory , I/O디바이스가 필요하게 된다.
  • 프로그램은 수동적인 존재, 프로세스는 능동적인 존재(화면에 이미지를 뿌리고 동작하고.. 등등)
  • 프로세스는 process state가 존재하고 그 위에서 execution stream 이 되어야한다.

Process state

  • 프로그램이 실행되는데 영향을 주는 정보들
  • 프로그램이 수행 되려면
    1. Memory 에 기억을 해야 한다.(Memory context) ->Code 세그먼트(기계어), Data 세그먼트 (프로그램의 전역변수), Stack세그먼트 (지역 변수)
    2. Register Values(CPU, I/O register) -> Hardware context
    3. Per-Process Kernel Info -> System context

Execution Stream

  • 프로세스가 지금까지 수행한 모든 명령어들의 순서
  • ex) 프로그램을 더블클릭해서 프로그램을 실행하는 그러한 모든 동작들 즉 첫 명령부터 지금까지 수행된 명령 들을 Execution Stream 이라 한다.

Multiprogramming vs Multiprocessing

  • Multiprogramming : 메인메모리에 여러 개의 Active한 프로세스가 올려져있으면 멀티 프로그래밍이라 한다.
  • Uniprogramming : 한 개가 올려라와 있는 것
  • Multiprocessing : 여러 개의 프로세서가 수행 되는 건데 CPU의 관점이다.
  • 멀티프로세싱을 하나의 프로세서에 두 개 이상의 프로그램이 교대로 실행되는 멀티프로그래밍과 혼동해서는 안된다. 멀티프로그래밍이라는 용어는 요즈음에는 대부분의 컴퓨터 운영체계가 멀티프로그래밍을 지원하므로 잘 쓰이지 않는 용어가 되었다. 또한 멀티프로세싱을, 프로그램들의 관리와 프로그램이 태스크로서 요청하는 시스템 서비스들이 공존하는 멀티태스킹이나, 컴퓨터를 통한 다중실행 경로의 관리와 여러 사용자들이 프로그램 하나를 공유하는 멀티스레딩 등과 혼동하지 않아야 한다.
  • 요즘 대부분의 OS는 멀티프로세스 멀티프로그래밍이다.
  • 과거에는 유니프로그래밍, 멀티프로세스를 사용한 적도 있다 (Swapping 사용)

Swapping

  • 메모리 부족 문제를 해결하기 위해 CPU를 사용하지 않는 프로세스의 데이터를 메모리에서 다른 저장 장치로 내보내고 CPU를 사용할 프로세스의 데이터를 메모리로 로드하는 것

프로세스 구현

Process Controll Block(PCB)

  • 프로세스의 데이터 구조는 Memory context, Hardware context, System context 로 나뉜다.
  • OS는 각 프로세스에 대한 정보를 유지한다. 그 프로세스의 정보들을 Process control block(PCB) 이라한다
  • PCB는 프로세스의 ID 정보, 스케줄링에 필요한 정보들을 가지고 있다.
  • 요즘 OS 멀티프로세싱이기(time sharing) 때문에 프로세스를 여러 개 가지고 있고 PCB 또한 여러 개가 존재한다. 여러 개의 PCB를 잘 관리해야 하는데 OS시스템 내부에 Array로 관리한다. 이를 Process table 이라 한다.
  • 프로세스를 구현하기 위해 제일 필요한 자료구조는 PCB, Process table 이다.
  • shell Programming

  • OS에게 명령어를 제공해주는 스크립트 프로그래밍
  • ex) Linux shell

프로세스 생명 주기

프로세스가 생성 되었을 때 부터 종료될 때 까지 발생하는 일련의 상태 변화

  • new 프로세스가 생성
  • Ready Queue : Ready 상태의 프로세스들을 관리하기 위한 Queue 형태의 자료구조, 각 노드를 PC로 Linked List로 연결하여 구현
  • Runing 상태에서는 프로세스 한개만 있을수 있다. 프로세스가 명령을 수행중
  • Ready 상태에는 여러개의 프로세스가 있을 수 있다. 프로세스가 runing 상태로 가기 위해 대기
  • waiting 상태에서는 프로세스가 특정 이벤트가 발생할 때 까지 대기
  • terminated 상태에서는 프로세스가 종료

프로세스 스케줄러

  • 스케줄러의 목적 : 각 프로세스 들이 공평하게 CPU를 공유할 수 있도록, 다음에 수행 시켜야할 프로세스를 선택하는 작업
  • 어떤 상황이 발생해서 CPU를 다른 프로세스에 넘겨줘야할 때 어느 프로세스를 골라야하느냐? -> OS 스케줄러가 해야 하는 일이다
  • OS 스케줄링은 다음과 같은 제약 조건을 가지고 있어야한다. Fair scheduling 하고 Protection 할 수 있어야한다.

운영체제 스케줄러 구성

  • 다음에 “어떤 프로세스를 고를까?” 를 결정하는 교체 가능한 policy 부분과
  • 공통적으로 CPU를 한 프로세스에서 다른 프로세스로 넘겨주는 기계적인 방법 이 있다

Policy

  • 다음에 수행될 프로세스를 선택하는 기준 (Scheduling Policy)

Dispatcher Mechanism

  • CPU를 한 프로세스에서 다른 프로세스로 넘겨주는 방법(Dispatcher)
  • 디스패처는 단순한 일을(기계적인 일) 한다.
  • OS 가장 깊숙한 곳에서 무한루프를 돈 다.
  • 주어진 프로세스를 어느 정도 돌린다.
  • 그만 돌리라는 명령이 오면 안전한 곳으로 대피 시킨다.
  • 그리고 나서 OS가 선택해준 다른 프로세스를 수행시킨다.

어떻게 디스패처를 컨트롤 하는가?

  • CPU의 컨트롤이 유저 프로세스에서 OS(디스패처)로 다시 OS(디스패처)에서 유저 프로세스로 원활하게 넘어가야한다. -> 즉 커널에서 유저로 유저에서 커널로 넘기는 작업
  • 어떻게 구현해야 하는가? 하드웨어? 소프트웨어? -> 하드웨어로 구현해야한다. (인터럽트)
  • 유저 모드에서 -> 커널모드로 변경해 함수(System call)인 디스패처가 돌면 된다.

Dispatcher

  • 디스패처가 수행된다고 하는 것은 커널로 실행 컨트롤이 진입하는 것이다. 유저 프로세스가 진행된다는 것은 실행컨트롤이 유저모드로 넘어 같다는 것이다.
  • 유저모드 -> 커널모드로 어떻게 넘기는가? : 인터럽트라는 메커니즘으로 구현했다.
  • 커널모드로 바꾸려면 모드체인지(인터럽트에 의해 발생)가 필요하다
  • 인터럽트가 발생하면 무조건 모드를 커널 모드로 바꾼다.
  • OS는 커널모드에서 수행되는 라이브러리(함수들의 집합) 이다.
  • 커널모드안에서 수행되는 이런 함수들을 System Call 함수라고 부른다. 또 다른 함수로 인터럽트 서비스 루틴이 있다.

마이크로프로세서가 커널모드와 유저모드를 구분하는 방식

  • Process Status Word 레지스터 안에 특정 비트를 Mode Bit로 사용한다.
  • ex) 인터럽트가 발생하면 하드웨어적으로 PSW 레지스터안의 비트가 0으로 바뀌어 커널모드가 된다.

Dispathcer가 호출된다는 것은 커널 모드의 함수(System call)중 하나인 Dispatcher가 불려지는 것이다. 디스패처가 호출되기 위해서는 인터럽트가 발생 되어야 한다.(커널 모드 변경이 필요하므로)

Dispathcer를 호출하는 2가지 방법(ISR 발생)

  • Non-preemptive Scheduling : 프로세스가 자발적으로 CPU를 양보하여 다른 프로세스를 수행하는 스케줄링
  • ex) 어떤 유저 프로세스가 CPU를 점유해서 사용하고 있었는데 CPU를 스스로 다른 프로세스에게 넘겨 주는 것 -> 내가 I/O를 요청했는데 I/O가 아직 준비가 되지 않았을 때
  • Trap을 사용하여 구현한다(S/W 인터럽트)

  • preemptive Scheduling : 운영체제가 강제로 프로세스로부터 CPU를 빼앗아 다른 프로세스를 수행하는 스케줄링
  • ex) 나는 더 돌고자 하는 의지가 있는데 운영체제가 강제로 빼앗음 -> Time sharing 스케줄링을 사용할 때 여러 사용자에게 지정된 CPU 시간을 제공하고 그 시간이 넘어갈 경우 OS가 CPU를 그 사용자에게서 빼앗아간다.
  • Timer 인터럽트 사용한다(H/W인터럽트)

System Call

  • OS가 제공해주는 라이브러리(Malloc 함수)를 사용하려면 어떻게 해야 할까? -> System Call 이라는 커널 함수를 호출한다. 이럴 경우 모드 체인지가 발생된다.
  • 소프트웨어 인터럽트 중에서 커널 함수를 호출하기 위해서 S/W 인터럽트가 사용되면 그런 것을 System Call 이라 한다.

Thread of Control

  • Thread of control(execution stream)의 정의: 그 프로세스가 첫 명령을 수행시킨 시점부터 지금까지 수행된 명령의 순서
  • 프로세스는 Context 와 Thread of Control 로 구성되어있다고 말했다.
  • 스택을 보게되면 그 프로그램의 엔트리 포인트 함수부터 불려 졌던 함수들이 꺼꾸로 들어가 있다. 그래서 그 프로세스의 수행된 이력을 볼 수 있다.
  • 이로 인해 State 중 유독 스택만은 Context(state)에 포함시키지 않고 Thread of Control을 구현하는 자료구조라고 말한다.
  • 그래서 프로세스는 Thread of control을 구현하는 스택과 나머지 Context(state)들로 구성이 된다.
  • 또 Stack은 해당 프로세스의 Run-Time Context 이다.
  • 프로세스가 유저모드에서 수행될 때는 유저모드 스택을 사용하고 커널 모드에서 수행될 때는 커널 모드 스택을 사용한다.

Context Switching

  • 디스패처가 호출되면 인터럽트가 자동적으로 발생 되 현재 수행중인 프로그램이 중단 된다.
  • 그럼 디스패처는 현재 수행중인 state를 안전한 곳으로 옮기고 다음 프로세스의 state를 읽어 와야 한다. 이를 Context Switching 이라 한다.

    Context Switching: 현재 수행 중인 프로세스의 State를 저장하고 다음 수행될 프로세스의 State를 불러오는 작업

Context switching을 통해 무엇을 대피(save)시켜야할까?

  • CPU 레지스터 들은 전부 대피시켜야한다!! (바로 다음 프로세스가 사용할 것이므로)
  • 메모리는 대피시켜야할까? 대피시키지 말아야할까? - 과거에는 전혀 대피시키지 않거나, 전부다 대피시키는 방법도 사용하였지면 현재 사용 되는 방식은 일부만 대피시키는 방법이다
  • 즉 메모리는 일부만 대피 하면 된다.(디스크로)
  • 커널 레지스터는 대피 시킬 필요 없다.
  • CPU Register 는 Main Memory로 대피시킨다.

Stack 동작 흐름

  • 유저 프로세스를 잘 수행하다가 0x100 번지 주소에 ADD 라는 명령을 수행 중 인터럽트가 발생!!
  • 현재 진행하던 0x100번지 ADD 명령수행을 마저 끝낸다.
  • 진행 명령이 끝나면 인터럽트를 체크하고
  • Process Status Word(PSW)의 Mode bit가 0으로 확 바뀌고
  • 그리고 마이크로프로세서는 어떤 인터럽트가 걸렸는지 확인(IRQ 넘버를 확인)하고 인터럽트 벡터 테이블을 뒤져서 해당 인터럽트 서비스 루틴에 시작 주소를 확인하고 그 곳으로 점프해 간다.
  • 그러면 인터럽트 서비스 루틴이 수행된다.
  • 인터럽트 서비스 루틴이 끝나면 복귀를 해야 한다.
  • 정확히 복귀해야할 위치는 ADD 명령이 끝난 다음 위치의 주소다 (0x104)
  • 이 주소를 어딘가에 대피시켜 놔야한다. 즉 인터럽트가 걸리기 직전에 0x104를 스택의 Top에 대피시킨다. 그리고 이 저장된 주소보다 더 먼저 PSW의 모드 비트를 저장시킨다. 왜냐하면 다시 원상태의 유저모드로 복귀해야하기 때문이다.
  • 인터럽트가 다 끝나면 Return From instruction을 수행시키면 스택의 Top을 뒤져 PSW을 우선적으로 Pop 하고 리턴어드레스를 Pop하여 원래 위치로 되돌아온다.
  • 참고로 마이크로프로세서의 PC 레지스터에 현재 명령의 위치가 저장되어있다(하드웨어적인 인터럽트 처리)

    즉 위의 결과로 볼 수 있듯이 인터럽트 서비스 루틴의 초반부에서 그 프로세스의 CPU 레지스터의 값들을 스택으로 대피시킨다는 것을 알게 되었다. 스택은 정말 중요한 요소로 작용하기 때문에 프로세서 레지스터 중 스택을 가리키는 레지스터를 따로 제공한다.