이 글은 혼자 공부하는 컴퓨터 구조 + 운영체제 (저자 : 강민철)의 책과 유튜브 영상을 참고하여 개인적으로 정리하는 글임을 알립니다.


프로세스

  • 프로그램은 실행되기 전까지는 그저 보조기억장치에 있는 데이터 덩어리
  • 보조기억장치에 저장된 프로그램을 메모리에 적재하고 실행하는 순간 프로세스가 된다.

 

프로세스 종류

  • Foreground Process : 사용자가 볼 수 있는 공간에서 실행되는 프로세스
  • Background Porcess : 사용자가 볼 수 없는 공간에서 실행되는 프로세스

백그라운드 프로세스 중에서 사용자와 직접 상호작용할 수 있는 백그라운드 프로세스도 있지만, 사용자와 상호작용하지 않는 백그라운드 프로세스도 있다.

이러한 사용자와 상호작용하지 않는 백그라운드 프로세스를 유닉스에서는 데몬(daemon)이라 부르고, 윈도우에서는 서비스(service)라고 부른다.

 


 

프로세스 제어 블록

모든 프로세스는 실행을 위해 CPU를 필요로 하지만, CPU 자원은 한정되어 있다.

즉, 프로세스의 수는 많은데 CPU는 프로세스의 수에 비해 매우 부족하다.

따라서 프로세스들은 돌아가며 한정된 시간만큼만 CPU를 이용한다.

  • 자신의 차례에 정해진 시간만큼 CPU이용
  • 타이머 인터럽트가 발생하면 차례 양보
타이머 인터럽트(타임아웃 인터럽트)
클럭 신호를 발생시키는 장치에 의해 주기적으로 발생하는 하드웨어 인터럽트

 

운영체제는 빠르게 번갈아 수행되는 프로세스의 실행 순서를 관리하고, 프로세스에 CPU를 비롯한 자원을 배분한다.

이를 위해 운영체제는 프로세스 제어 블록(PCB:Process Control Block)을 이용한다.

 

프로세스 제어 블록(PCB)

  • 프로세스 관련 정보를 저장하는 자료 구조
  • 마치 상품에 달린 태그와 같은 정보
  • 운영체제는 수 많은 프로세스들 사이에서 PCB로 특정 프로세스를 식별하고 해당 프로세스를 처리하는 데 필요한 정보 판단
  • 프로세스 생성 시 커널 영역에 생성, 종료 시 폐기
  • 새로운 프로세스 생성 = 운영체제가 PCB 생성, 프로세스가 종료 = 운영체제가 해당 PCB를 폐기

 

PCB에는 운영체제마다 차이가 있지만 대표적으로 아래와 같은 정보가 담긴다.

  • 프로세스 ID (PID:Process ID) : 특정 프로세스를 식별하기 위해 부여하는 고유한 번호
  • 레지스터 값 : 프로세스는 자신의 차례가 돌아오면 이전까지 작업했던 내용(레지스터 중간값)을 복구한다. 또한 작업을 모두 마치지 못하고 CPU를 반납해야 한다면 이전까지 작업 내용을 레지스터에 백업한다.
  • 프로세스 상태 : 현재 프로세스가 어떤 상태인지를 기록(입출력 장치를 기다리는 상태인지, CPU를 이용 중인 상태인지 등)
  • CPU 스케줄링 정보 : 프로세스가 언제, 어떤 순서로 CPU를 할당받을지에 대한 정보
  • 메모리 관리 정보 : 프로세스가 어느 주소에 저장되어 있는지에 대한 정보(베이스 레지스터와 한계 레지스터 값, 페이지 테이블 정보)
  • 사용한 파일과 입출력 장치 목록 : 어떤 입출력 장치가 이 프로세스에 할당되었는지, 어떤 파일들을 열었는지에 대한 정보

 


 

문맥 교환(Context Switch)

한 프로세스(프로세스 A)에서 다른 프로세스(프로세스 B)로 실행 순서가 넘어가면 기존에 실행되던 프로세스 A는 지금까지의 중간 정보를 백업한다.

백업하는 정보로는 프로그램 카운터를 비롯한 각종 레지스터 값, 메모리 정보, 열었던 파일, 사용한 입출력 장치 등이 있다.

이러한 중간 정보, 즉 하나의 프로세스 수행을 재개하기 위해 기억해야 할 정보를 문맥(context)이라고 한다.

PCB에 기록되는 정보들을 문맥이라고 봐도 무방하다.

 

실행 문맥을 잘 기억해 두면 언제든 해당 프로세스의 실행을 재개할 수 있기 때문에 프로세스가 CPU를 사용할 수 있는 시간이 다 되거나 예기치 못한 상황이 발생하여 인터럽트가 발생하면 운영체제는 해당 프로세스의 PCB에 문맥을 백업한다. 이후 다시 자신의 차례가 오면 문맥을 복구한다.

이러한 과정을 프로세스끼리 반복한다면 그것이 문맥 교환이다.

정리하자면 기존 프로세스의 문맥을 PCB에 백업하고, 새로운 프로세스를 실행하기 위해 문맥을 PCB로부터 복구하여 새로운 프로세스를 실행하는 것을 문맥 교환이라고 한다.

 

문맥 교환은 여러 프로세스가 끊임없이 빠르게 번갈아 가며 실행되는 원리이다.

문맥 교환이 자주 일어나면 프로세스는 그만큼 빨리 번갈아 수행되기 때문에 우리들의 눈에는 프로세스들이 동시에 실행되는 것처럼 보인다.

문맥 교환을 너무 자주하면 오버헤드가 발생할 수 있기 때문에 문맥 교환이 자주 일어난다고 해서 반드시 좋은 건 아니다.

 


 

프로세스의 메모리 영역

프로세스가 생성되면 커널 영역에 PCB가 생성된다. 하나의 프로세스는 사용자 영역에 크게 코드 영역, 데이터 영역, 힙영역, 스택 영역으로 나뉘어 저장된다.

 

코드 영역(code segment) (=텍스트 영역(text segment))

  • 실행할 수 있는 코드, 기계어로 이루어진 명령어 저장
  • 데이터가 아닌 CPU가 실행할 명령어가 담기기에 쓰기가 금지된 영역(read-only)
  • 정적 할당 영역(크기가 고정된 영역)

 

데이터 영역(data segment)

  • 잠깐 썼다가 없앨 데이터가 아닌 프로그램이 실행되는 동안 유지할 데이터 저장
  • ex) 전역변수
  • 정적 할당 영역(크기가 고정된 영역)

 

힙 영역(heap segment)

  • 프로그램을 만드는 사용자, 즉 프로그래머가 직접 할당할 수 있는 저장공간
  • 프로그래밍 과정에서 힙 영역에 메모리 공간을 할당했다면 메모리 반환은 필수적
  • 메모리 반환을 하지 않으면 메모리 누수 발생 주의
  • 동적 할당 영역(크기가 가변적인 영역)

 

스택 영역(stack segment)

  • 데이터가 일시적으로 저장되는 공간
  • 잠시 쓰다가 버릴 값들이 저장되는 공간
  • ex) 매개 변수, 지역 변수
  • 동적 할당 영역(크기가 가변적인 영역)

 

힙 영역과 스택 영역의 크기는 가변적

  • 일반적으로 힙 영역은 낮은 주소 -> 높은 주소로 할당
  • 일반적으로 스택 영역은 높은 주소 -> 낮은 주소로 할당
  • 힙 영역과 스택 영역은 크기가 가변적이기 때문임