다음은 반효경 교수님의 ‘운영체제와 정보기술의 원리’ CH5. 프로세스 관리를 읽고 정리한 내용입니다 🙌



🌩 1. 프로세스의 개념

  • 프로세스란 실행 중인 프로그램이다.
  • 프로세스는 CPU를 획득해서 코드를 수행하고 CPU를 반환하고 입출력 작업을 수행하기도 한다.
  • 프로세스 문맥 (context) - 프로세스가 현재 어떤 상태에서 수행되고 있는 규명하기 위해 필요한 정보
    • 여러 프로세스가 CPU를 사용하면서 중간에 CPU를 다른 프로세스에게 넘겨야 한다.
    • 이때 다시 이어서하기 위한 필요 정보가 있는데 그것을 프로세스 문맥이라고 한다.
    • 프로세스의 주소 공간, 레지스터의 값, 시스템 콜을 통해 커널에서 수행한 일의 상태, 프로세스에 대해 커널이 관리하고 있는 여러 정보들을 포함한다.
  • 프로세스 문맥은 3가지로 나뉜다.
    1. 하드웨어 문맥
      1. CPU의 수행 상태를 나타낸다.
      2. 프로그램 카운터 값, 각종 레지스터에 저장하고 있는 값들이다.
    2. 프로세스의 주소 공간
      1. 코드, 데이터, 스택으로 이루어진 프로세스의 독자적인 주소 공간이다.
    3. 커널상의 문맥
      1. PCB 와 커널스택이 프로세스에 대한 커널에 위치하는 자료구조이다.

🌩 2. 프로세스의 상태

  • 실행(running), 준비(ready), 봉쇄(blocked, wait, sleep)
  • 실행 - 프로세스가 CPU를 봉하고 기계어 명령을 실행하고 있는 상태
    • 실제로 실행 상태에 있는 프로세스는 매 시점 하나이다.
  • 준비 - 프로세스가 CPU만 보유하면 명령을 실행할 수 있지만 CPU를 획득하지 못한 상태
  • 봉쇄 - CPU를 할당 받더라도 명령을 실행할 수 없는 프로세스의 상태
    • 입출력 작업이 진행 중인 경우
  • 프로세스의 상태를 나누는 이유는 컴퓨터의 자원을 효율적으로 관리하기 위해서다.
  • 이외에도 시작과 종료 상태가 있다.
    • 시작 - 프로세스에 대한 자료구조는 생성 되었지만 메모리 획득을 승인받지 못한 상태
    • 종료 - 프로세스가 종료되었으나 운영체제가 관련된 자료구조를 완전히 정리하지 못한 상태
  • 프로세스는 앞의 상태 중 하나에 머물러 있으며, 시간의 흐름에 따라서 변한다.

프로세스의 상태 흐름

  • 프로세스의 문맥이 교환되는 것을 Context switching이라고 한다.
    • 한 프로세스가 진행 중일 때 타이머 인터럽트가 발생한다.
    • 타이머 인터럽트 처리루틴에 따라서 현재 진행중이던 프로세스의 문맥을 저장하고 준비 상태의 프로세스 중 하나를 선택한다.
    • 본래 수행 중이던 프로세스를 준비 상태로 내리고 새로운 프로세스가 실행 상태가 된다.
    • 실행할 프로세스에 대한 문맥을 세팅한다.
  • CPU 디스패치(dispatch) - 준비 상태에 있는 프로세스 중 CPU를 할당받을 프로세스를 선택하고 제어권을 넘겨받는 과정

입출력을 요청한 프로세스의 상태변화

  • 디스크 입출력은 오랜 시간이 걸리기 때문에 이 시간동안 해당 프로세스는 봉쇄 상태가 된다.
  • 그 동안 준비 상태의 프로세스 들을 CPU 스캐줄러가 선정해 CPU를 할당하고 해당 프로세스는 실행 상태로 변경이 된다.
  • 입출력 요청 프로세스는 디스크 입출력 큐에 대기하다가 디스크 컨트롤러부터 서비스를 받는다.
  • 완료 후 디스크 컨트롤러가 CPU에게 인터럽트로 입출력 완료를 알린다.
  • CPU는 인터럽에 대한 루틴을 수행한다.
    • 이때 당시에 CPU에서 진행중이던 프로세스가 사용자모드에서 커널 모드로 바뀐다.
    • 관련이 없는 프로세스지만 해당 프로세스 중 인터럽트가 발생했기 때문에 해당 프로세스가 커널 모드로 진입했다고 판단하도록 한다.
  • 봉쇄 상태의 프로세스는 준비 상태로 바뀌고, 로컬버퍼에 있는 내용을 메모리로 이동시키는 업무를 수행한다.
  • 인터럽트 처리 루틴이 완료되면 직전 프로세스가 다시 수행되거나 입출력 완료 프로세스의 우선순위가 높다면 해당 프로세스가 수행된다.

🌩 3. 프로세스 제어블록

  • Process Control Block - 운영체제가 시스템 내의 프로세스들을 관리하기 위해 프로세스마다 유지하는 정보들을 담는 커널 내 자료구조
    • 커널 메모리의 데이터 영역에 위치한다.
  • 다음 요소들로 구성되어 있다.
    • 프로세스의 상태
      • CPU를 할당해도 되는지 여부를 결정
    • 프로세스 카운터 값
      • 다음 수행할 명령어 위치 가리킴
    • CPU 레지스터 값
      • CPU 연산을 위해서 현 시점에서 레지스터에 특정 값을 저장
    • CPU 스캐줄링 정보
      • 스캐줄링에 필요한 정보
    • 메모리 관리 정보
      • 메모리 할당에 필요한 정보
    • 자원 사용 정보
      • 사용자에게 자원 사용 요금을 계산하여 청구
    • 입출력 상태 정보
      • 프로세스가 오픈한 파일 정보 등 프로세스의 입출력 관련 상태 정보

🌩 4. 문맥교환

  • Context Switch - 하나의 사용자 프로세스로부터 다른 사용자 프로세스로 CPU의 제어권이 이양되는 과정
    • 타이머 인터럽트가 발생하면 직전 수행 프로세스의 문맥을 저장하고 새로운 프로세스에게 CPU를 이양한다.
  • 기존에 보유하고 있던 프로세스의 문맥 저장
    • PC 값 등을 자신의 PCB에 저장
  • 새로 할당받은 프로세스
    • 저장했던 문맥을 PCB에서 하드웨어로 복원
  • 타이머 인터럽트 외에도 실행 중이던 프로세스가 입출력 요청이나 다른 조건을 충족하지 못해서 CPU를 뺏기고 봉쇄상태가 될 때도 문맥교환이 발생한다.
  • 프로세스 실행 상태 중 인터럽트나 시스템 콜로 인해 CPU의 제어권이 운영체제로 넘어가면 실행 중이던 프로세스의 문맥을 일부 PCB에 저장하지만 이 과정은 문맥교환이라고 하지 않는다.
    • 단순히 해당 프로세스의 모드가 사용자모드에서 커널모드로 바뀌는 것 뿐이다.
  • 모드변경보다 문맥교환이 훨씬 많은 오버헤드가 발생한다. 따라서 타이머의 단위가 작아 문맥교환이 지나치게 자주 일어나면 오버헤드가 커진다.
    • 하지만 단위가 너무 크면 시분할 시스템의 의미가 퇴색되므로 적절한 시간 할당이 중요하다.

🌩 5. 프로세스를 스케줄링하기 위한 큐

  • 운영체제는 준비상태에 있는 프로세스들을 ready queue에 두고 줄 앞에 프로세스에게 CPU를 할당한다.
    • 줄을 세우는 방식은 CPU 스캐줄링 방식에 따라서 달라진다.
  • 운영체제 하드웨어 자원을 기다리는 프로세스를 위한 자원별 장치 큐 device queue가 있다.
    • ex. 디스크 입출력 큐 disk I/O queue, 키보드 입출력 큐 등등
  • 소프트웨어 자원을 기다리기 위한 자원 큐도 있다.
    • 어떤 공유 데이터에 대한 접근 권한 등등
    • 일관성을 위해 해당 공유 데이터에 접근 중인 프로세스가 다 사용하고 반납할 때까지 접근 권한을 주면 안된다.
    • 이 관리를 자원 큐를 통해서 한다.
  • 이 모든 큐들은 커널의 데이터 영역에 둔다.
    • 프로세스의 CPU 대기, 입출력 대기 등의 정보를 커널이 총체적으로 관리한다.
  • 작업 큐 (job queue) - 시스템 내의 모든 프로세스를 관리하기 위한 큐로 프로세스의 상태와 무관하게 현재 시스템 내에 있는 모든 프로세스가 작업 큐에 속한다.
    • 작업 큐에 있다고 반드시 메모리가 있는 것은 아니다.
    • 작업 큐가 가장 넓은 개념이고 준비 큐와 장치큐이 있는 프로세스는 모두 작업 큐에 속해있다.
  • 큐는 각 프로세스의 PCB를 연결 리스크 형태로 관리하고 포인터로 순서를 정한다.

🌩 6. 스케줄러

  • 스캐줄러 - 어떤 프로세스에게 자원을 할당할지 결정하는 운영체제 커널의 코드
    • 장기 스캐줄러와 단기 스케줄러
  • 장기 스캐줄러 (long term scheduler) - 작업 스캐줄러 (job scheduler) 이며 어떤 프로세스를 준비 큐에 진입시킬지 결정
    • CPU에 실행되기 위해서는 프로세스가 메모리를 보유해야하므로 장기 스캐줄러는 프로세스에 메모리 보유 문제에 관여한다.
    • 수십 초 내지 수 분 단위로 가끔 호출되므로 상대적으로 느린 것이 허용된다.
    • 메모리에 동시에 올라가 있는 프로세스의 수 (degree of multiprogramming)을 조절한다.
    • 하지만 현대의 시분할 시스템은 메모리가 훨씬 커서 장기 스케줄러 없어 바로 프로세스에 메모리를 할당해 준비큐에 넣어준다.
  • 단기 스캐줄러 (short term scheduler) - 준비 프로세스 중 어떤 프로세스를 다음에 실행상태로 만들지 결정
    • 준비 큐에 있는 것들 중 어떤 프로세스에게 CPU를 할당할지 결정하는 것
    • 타이머 인터럽트 발생시 단기 스캐줄러가 호출된다.
    • 밀리초 단위로 빈번하게 호출이 되므로 수행 속도가 빨라야 한다.
  • 중기 스캐줄러 (medium term scheduling) - 메모리에 적재된 프로세스의 수를 동적으로 조절
    • 너무 많은 프로세스가 메모리에 적재되어 시스템 효율이 떨어지는 것을 관리한다.
    • 메모리에 당장 필요한 프로세스의 주소 공간도 모자라면 디스크 입출력이 수시로 발생하여 시스템의 성능이 저하된다.
    • 중기 스캐줄러는 이 경우 메모리의 프로세스 중 일부를 선정 해 메모리를 뺏고 해당 내용을 스왑 영역에 저장한다 ⇒ swap out
    • 프로세스당 보유 메모리가 지나치게 적다면 일부 프로세스를 메모리에게 디스크로 스왑 아웃시키는 역할을 수행한다.
    • 봉쇄 상태에 있는 프로세스들이 가장 먼저 스왑 아웃된다. 그럼에도 부족하다면 타이머 인터럽트 발생 후 준비 큐로 이동하는 프로세스들을 추가적으로 스왑 아웃한다.
      • 다시 CPU를 할당 받을 때까지 시간이 걸리기 때문이다.
  • 프로세스의 중지(suspended, stopped) 상태
    • 외부적인 이유로 프로세스의 수행이 정지된 상태
    • 디스크로 스왑 아웃된 프로세스의 상태이다.
    • 중지준비 상태 - 준비 상태의 프로세스가 디스크로 스왑 아웃된 것
    • 중지봉쇄 상태 - 봉쇄 상태의 프로세스가 디스크로 스왑 아웃된 것
      • 중지봉쇄 상태에서 해당 작업이 끝나면 중지준비 상태로 변경된다.
    • 이 경우들은 프로세스가 메모리를 보유하지 않고 통째로 디스크로 스왑 아웃 된 상태이다.

🌩 7. 프로세스의 생성

  • 시스템 부팅된 후 최초 프로세스는 운영체제가 직접 생성한다.
  • 이후부터는 이미 존재하는 프로세스가 다른 프로세스를 복제 생성한다.
    • 생성하는 프로세스를 부모 프로세스, 생성되는 프로세스를 자식 프로세스라고 한다.
  • 자식 프로세스가 먼저 죽고 부모 프로세스가 이에 대한 처리를 한다.
    • 부모 프로세스가 종료되기 위해서는 생성된 자식 프로세스가 모두 종료된 후에야 종료될 수 있다.
  • 프로세스의 자원
    • 운영체제와 자원의 종료에 따라 획득하는 방식이 다르다.
      • 운영체제로 직접 자원 할당
      • 부모 프로세스와 자원을 공유하여 사용
  • 프로세스 수행 모델
    • 부모와 자식이 공존하며 수행
      • 부모와 자식이 CPU를 획득하기 위해 경쟁함
    • 자식이 종료(terminated) 될 때까지 부모가 기다리는(wait) 모델
      • 자식이 종료될 때까지 부모 프로세스는 봉쇄 상태에 머물다가 자식 종료 후 부모 프로세스가 준비 상태가 되어 CPU를 획득할 수 있음
  • 프로세스가 생성될 때 독자적인 주소 공간을 갖는다.
    • 자식 프로세스가 생성될 때 부모 프로세스의 주소 공간을 복사하여 별도의 주소 공간을 생성하고 새로운 프로그램 내용을 덮어씌워 실행한다.
      • 유닉스에서 fork() 시 자식 프로세스가 생성되고 부모와 똑같은 커널 내 정보와 주소 공간 정보를 가진 상태로 복사된다. (프로세스 id는 다르다)
      • 이후 exec() 시 새로운 주소 공간을 덮어씌운다.

프로세스의 종료

  • 자발적 종료
    • 코드의 마지막에 exit()라는 시스템 콜을 통해 (없다면 컴파일러가 자동으로 삽입) 종료하고 운영체제는 해당 프로세스로부터 자원을 회수한다.
  • 비자발적 종료
    • 부모 프로세스가 자식 프로세스의 수행을 강제로 종료하며 abort()로 이루어진다.
    1. 자식 프로세스가 할당 자원의 한계 이상의 자원을 요구할 때
    2. 자식 프로세스에게 할당된 작업이 필요하지 않을 때
    3. 부모 프로세스가 종료(exit) 되는 경우에 발생한다.
  • 종료되는 프로세스는 자식 프로세스를 계속 실행하기 위해서 종료되지 않을 다른 프로세스의 양자로 보내어 계속 수행할 수 있도록 할 수 있다.

자식 프로세스 생성

  • fork() 시스템 콜로 CPU제어권을 커널로 넘겨 fork() 호출 프로세스를 복제해 자식 프로세스를 생성
    • 부모와 모든 문맥(주소 공간, PC, 레지스터 상태, PCB, 커널스택 등)을 동일하게 가진 자식 프로세스 생성한다.
      • 따라서 자식 프로세스는 부모 프로세스의 현재 수행 시점부터 수행하게 된다. (PC 등의 값을 그대로 복제하므로)
    • 식별자는 부모 프로세스와 다르다.
    • 함수의 결과값은 자식은 0, 부모는 양수이다. 이 값으로 자식과 부모 프로세스를 분기할 수 있다. 하지만 여전히 분기문을 가진 코드 또한 동일한 것을 지닌 상태이다.
  • 자식에게 독자적인 프로그램 수행이 가능하도록 유닉스에서 새로운 주소 공간에 새로운 프로그램을 exec() 를 통해 덮어씌울 수 있도록 한다.
  • fork(), exec(), exit() , wait()는 모두 특권명령이다.
    • wait()은 자식 프로세스가 종료될 때까지 부모 프로세스를 봉쇄 상태에 머무르게 하는 것이다.
    • 이것으로 자식과 부모의 동기화 (synchronization)이 가능하다.
    • 자식 프로세스가 종료되면 다시 준비 큐에 삽입되어 CPU 할당 받을 수 있다.

🌩 8. 프로세스 간의 협력

  • 부모 프로세스와 자식 프로세스는 독자적인 메모리 구조를 가지므로 독립적인 관계가 된다.
  • 프로세스간 협력할 때 서로 주소 공간을 참조하지 않으면서 정보를 주고받을 수 있는 매커니즘이 필요하다.
  • IPC(Inter-Process Communication) - 운영체제가 제공하는 하나의 컴퓨터 안에서 실행 중인 프로세스 간 협력 매커니즘
    • 프로세스간의 통신(communication)과 함께 공유 데이터의 일관성을 위한 동기화를 보장해주어야 한다.
    • 메세지 전달(message passing)과 공유메모리(shared memory) 방식이 있다.
      • 차이는 shared data가 있는 것과 없는 것이다.

메세지 전달

  • 프로세스간 공유 데이터가 없이 메세지를 주고받으며 통신한다. 메세지 전달은 직접하지 못하고 커널이 전달한다.
  • 커널이 제공하는 send(), receive() 연산으로 시스템 콜 방식으로 요청해 메세지를 전달한다.
  • 메세지를 전달하는 연산은 특권명령이다.
  • 통신하기 원하는 두 프로세스는 communication link를 생성하고 send(), receive()를 통해 메세지를 주고 받는다.
    • communication link는 물리적인 방법, 논리적인 방법 두 가지로 구현할 수 있다.
  • 직접 프로세스에게 전달하는 방식과 메일 박스를 통해 간접적으로 전달하는 방식으로 나뉜다.
    1. 직접 통신 (direct communication)
      1. 통신하려는 프로세스를 직접 명시하고 받는 프로세스도 직접 명시한다.
      2. 커뮤니케이션 링크는 자동으로 생성되고 하나의 링크는 한 쌍의 프로세스에게 할당된다.
      3. 대부분의 링크는 양방향이며 단 하나의 링크만 서로 존재한다.
    2. 간접 통신 (indirect communication)
      1. 메일박스 또는 포트로 메시지를 전달받는다. 메일박스는 고유의 id가 있어서 해당 메일박스를 공유하는 프로세스들끼리만 통신을 할 수 있다.
      2. 커뮤니케이션 링크는 메일박스를 공유하는 경우에만 생성된다.
      3. 하나의 링크가 여러 프로세스에게 할당될 수 있고, 각 프로세스 쌍은 여러 링크를 공유할 수 있다.
      4. 링크는 단방향, 양방향일 수 있다.
      5. 새로운 메일박스를 생성하는 연산, 메세지 send(), receive() 연산, 메일박스 삭제 연산을 할 수 있다.
      6. 간접통신에서 메세지 대상 및 수신자는 A라는 메일박스로 통일된다.
      7. 메일박스 공유로 수신 대상의 혼란을 제어하기 위해 2개의 프로세스에게만 링크를 할당할 수 있다.
        • 또는 링크의 receive() 연산을 매 시점 하나의 프로세스만 수행할 수 있도록 한다.
        • 시스템이 메세지 수신자를 임의로 결정해 누가 받았는지 송신자에게 통신해준다.

공유메모리 shared memory

  • 프로세스들의 메모리 주소 공간 일부를 공유한다.
  • 각 프로세스는 독립된 주소 공간을 가지고 있다. 이 주소 공간(가상 메모리)가 물리 메모리로 매핑될 때 공유메모리 주소 영역은 동일한 물리 메모리 영역으로 매핑된다.
  • 통신이 쉬운 인터페이스이지만 데이터 일관성 문제가 발생할 수 있다. 이 문제는 커널이 책임지지 않으며 프로세스들끼리 직접 동기화 문제를 해결해야 한다.