Skip to content

혼자 공부하는 컴퓨터 구조+운영체제

운영체제 시작하기

운영체제를 알아야 하는 이유(완료)

요약: 하드웨어를 조작하는 운영체제를 이해하면 하드웨어와 프로그램을 더 깊이 이해하게 되고 문제 해결 능력이 증가한다.

운영체제는 실행할 프로그램에 자원을 할당하고, 프로그램이 문제 없이 실행되도록 돕는 프로그램이다. 결국 운영체제도 프로그램이기에, 운영체제는 커널 영역이라는 메모리 영역에 적재된다(반대로 응용 프로그램이 적재되는 메모리 영역을 사용자 영역이라고 한다).

운영체제는 컴퓨터 하드웨어와 응용 프로그램 사이의 인터페이스 역할을 한다. 따라서 하드웨어를 조작하는 운영체제를 이해하면 하드웨어와 응용 프로그램을 더 깊이 이해하게 되고 문제 해결의 실마리를 찾을 수 있게 된다.

운영체제의 큰 그림(완료)

요약:

  • 운영체제의 핵심은 커널이다.
  • 사용자 프로그램은 컴퓨터 자원에 직접 접근할 수 없기에 시스템콜을 사용해 운영 체제에 해당 작업을 처리하도록 요청한다.
  • 시스템콜이 발생하면 CPU는 사용자 모드에서 커널 모드로 전환한다. 이후 커널 코드 실행이 끝나면 다시 사용자 모드로 전환된다.

운영체제의 핵심은 커널이다. 커널은 운영체제의 핵심 기능을 담당하는데 대표적으로 자원 접근 및 할당, 프로세스 관리, 파일 시스템 관리 등을 처리한다.

일반적으로 사용자 프로그램은 직접 컴퓨터 자원에 접근할 수 없다. 이는 자원을 체계적으로 관리하고 사용자 프로그램에 오류가 발생했을 때 컴퓨터 전체에 악영향을 미치는 것을 방지하기 위함이다. 따라서 사용자 프로그램은 운영체제에게 자원을 사용할 때 운영 체제에 요청을 해야 하는데 이를 시스템콜이라 한다.

시스템콜은 일종의 소프트웨어 인터럽트로, 시스템콜을 사용하면 CPU는 지금까지의 작업을 백업하고, 커널 영역 내에 시스템콜을 수행하는 코드를 실행한 뒤 다시 기존에 실행하던 응용 프로그램으로 복귀하여 실행을 계속해 나간다.

참고로 CPU가 명령을 수행하는 모드를 사용자 모드와 커널 모드로 나누는데 사용자 모드는 사용자 프로그램의 코드를 실행시키는 모드이고(자원 접근 불가), 커널 모드는 커널의 기능을 사용하고 자원에 접근할 수 있는 모드이다.

프로세스와 스레드

프로세스 개요(완료)

요약:

  • 프로세스는 실행중인 프로그램이다.
  • 운영체제는 프로세스를 관리하기 위해 PCB를 커널 영역에 저장하고 이용한다.
  • 프로세스 간에 실행을 전환하는 것을 문맥 교환이라고 한다.
  • 프로세스는 메모리에 코드 영역, 데이터 영역, 스택 영역, 힙 영역으로 나뉘어 배치된다.

프로세스는 메모리에 적재된 실행 중인 프로그램이다. 프로세스는 foreground process와 background process로 구분할 수 있다.

  • foreground process: 사용자가 보이는 앞에서 실행되는 프로세스
  • background process: 사용자가 보지 못하는 뒤에서 실행되는 프로세스

프로세스는 실행되기 위해 CPU가 필요하지만 CPU는 한정적이다. 따라서 프로세스는 한정된 시간동안 CPU를 이용하고 시간이 다 됐다고 알리는 타이머 인터럽트 발생 시 차례를 양보한다.

운영체제는 빠르게 번갈아 실행되는 프로세스를 관리하기 위해 프로세스의 메타 데이터가 저장된 자료구조, PCB(Process Control Block)를 커널 영역에 저장하고 이용한다.

다음은 PCB에 저장된 데이터들이다.

  • PID: 프로세스 식별을 위해 부여된 고유한 번호가 저장된다.
  • 레지스터 값: 프로세스는 실행 중 CPU를 양보하게 됐을 때 해당 프로세스가 실행하며 사용했던 레지스터 값을 저장한다. 이후 다시 CPU 사용 차례가 됐을 때 사용했던 레지스터 값을 복원하여 이전까지 진쟁했던 작업들을 그대로 이어 실행한다.
  • 프로세스 상태: 현재 프로세스가 어떤 상태인지에 대한 정보로 생성(New), 준비(Ready), 실행(Running), 대기(Blocked), 종료(Terminated) 상태가 있다.
  • CPU 스케쥴링 정보: 프로세스가 언제, 어떤 순서로 CPU를 할당받을지에 대한 정보갸 저장된다.
  • 메모리 관리 정보: 프로세스의 주소를 알기 위한 페이지 테이블 정보와, 베이스 레지스터, 한계 레지스터 값과 같은 정보들이 들어간다.
  • 사용할 파일과 입출력 장치 정보: 프로세스에 어떤 입출력 장치가 할당되었는지, 어떤 파일들을 열었는지에 대한 정보들이 저장된다.

문맥 교환(Context Switching)

문맥은 현재 실행중인 프로세스의 상태로, 프로그램 카운터, 레지스터 값, 스택, 메모리 정보등이 포함된다.

문맥 교환이란 프로세스의 실행 순서가 넘어갈 때 기존 프로세스의 문맥을 PCB에 복원하고 새로운 프로세스의 문맥을 PCB로부터 복구하여 새로운 프로세스를 실행하는 것이다.

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

프로세스의 메모리 영역

사용자 메모리 영역에 저장된 프로세스는 코드 영역, 데이터 영역, 힙 영역, 스택 영역으로 나누어 저장된다. 다음 그림은 프로세스의 메모리 영역을 나타낸다.

프로세스 상태와 계층 구조

요약:

  • 프로세스는 빠르게 번갈아 실행되는 과정에서 생성, 준비, 실행, 대기, 종료 상태를 갖는다.
  • 프로세스는 실행 도중 시스템콜을 통해 다른 프로세스를 생성할 수 있다.

프로세스 상태

운영체제는 프로세스의 상태를 PCB에 기록한다.

다음은 프로세스의 상태이다.

  • 생성(New): 프로세스가 막 생성되어 PCB를 할당 받은 상태
  • 준비(Ready): 언제든 CPU를 할당 받아 실행 가능한 상태
  • 실행(Running): CPU를 할당 받아 실행 중인 상태
  • 대기(Blocked): 프로세스가 특정 이벤트(예: I/O 작업 완료)를 기다리는 상태. 이 상태에서 프로세스는 CPU를 사용할 수 없다.
  • 종료(Terminated): 프로세스가 종료된 상태. 이후 프로세스와 PCB를 메모리에서 폐기한다.

프로세스 계층 구조

프로세스는 실행 중 시스템콜을 통해 다른 프로세스를 생성할 수 있는데 생성된 프로세스를 자식 프로세스, 생성한 프로세스를 부모 프로세스라고 한다. 이런 과정을 도표로 그리면 아래와 같은 트리구조를 띄는데, 이를 프로세스 계층 구조라고 한다.

다음은 프로세스가 자식 프로세스를 생성하는 과정이다.

  1. fork() 함수를 호출하여 자신의 복사본을 자식 프로세스로 생성한다.
  2. exec() 함수를 호출하여 자신의 메모리 공간을 다른 프로그램으로 교체한다.

스레드

요약

  • 스레드란 프로세스 내의 실행 흐름 단위이다.
  • 스레드는 프로세스의 자원을 공유하기에 멀티프로세스 간 통신보다 스레드 간 통신이 빠르고 간단하다(하지만 동기화 및 데드락 같은 복잡한 이슈를 주의해야 한다.)

스레드는 프로세스 내의 실행흐름의 단위로 하나의 프로세스는 하나 이상의 스레드를 갖는다. 스레드는 프로세스 자원을 공유한채 실행에 필요한 최소한의 데이터만을 갖고 실행된다.

다음은 스레드의 구성 요소이다.

  • 스레드 ID
  • 프로그램 카운터를 비롯한 레지스터 값
  • 스택

초기에는 여러 작업을 할 때 멀티 프로세스를 사용했지만 자원을 공유하지 않기 때문에 문맥 교환(context switch) 오버 헤드 발생 스레드는 프로세스 내부에 존재하기 떄문에 자원을 공유한다.

멀티 프로세스와 멀티 스레드

  • 멀티 프로세스: 여러 프로세스를 동시에 실행하는 것
  • 멀티 스레드: 여러 스레드를 동시에 실행하는 것

스레드는 스택, 레지스터 값, 스레드 ID 값만 다르고 같은 프로세스 자원을 공유하기 때문에 협력과 통신에 유리하다. 하지만 자원을 공유한다는 특징으로 인해 하나의 스레드에 문제가 생기면 프로세스 전체에 문제가 생길 수 있다.

CPU 스케쥴링

CPU 스케쥴링 개요

요약

CPU 스케쥴링이란 운영체제가 다수의 프로세스 혹은 스레드 중에서 어떤 것에 다음 CPU 자원을 할당할지 결정하는 과정이다.

운영체제는 PCB에 프로세스 우선순위를 저장하고 우선순위가 높은 순서대로 CPU 자원을 할당한다.

스케쥴링 큐

스케쥴링 큐란 자원 이용을 원하는 프로세스가 큐에 들어가 줄서는 것을 의미한다. 프로세스에 자원을 할당할 때마다 CPU가 모든 PCB를 탐색하여 우선 순위가 가장 높은 프로세스를 찾는 것은 비효율적이다.

따라서 스케쥴링 큐를 구현하고 프로세스의 우선순위를 관리한다.

CPU 스케쥴링 알고리즘

요약

CPU 스케쥴링 알고리즘 7개 있다.

프로세스 동기화

동기화란

요약

멀티 프로세스, 멀티 스레드로 작업을 하다보면 각 프로세스와 스레드가 서로 다른 공유 자원의 값을 갖게 될 수 있다. 모든 프로세스와 스레드가 같은 자원 값을 유지하도록 하는 것을 동기화라고 한다.

동기화를 하기 위해서는 코드 시행 순서를 컨트롤 하는 방법과, 한 자원에 대해서 동시에 여러 프로세스가 접근하지 못하게 하는 방법이 있다.

공유 자원과 임계 구역

  • 공유 자원(Shared Resource): 여러 프로세스와 스레드가 공유하는 자원으로 전역 변수, 입출력 장치, 보조기억장치 등이 될 수 있다.
  • 임계 구역(Critical Section): 여러 프로세스와 스레드가 동시에 접근하면 문제가 발생할 수 있는 코드 영역으로 주로 공유 자원에 접근하거나 수정하는 코드를 포함한다.
  • 레이스 컨디션(Race Condition): 여러 프로세스나 스레드가 임계 구역에 동시에 접근하여 자원의 일관성이 깨진 상태

동기화 기법

뮤텍스 락

뮤텍스 락은 여러 프로세스가 동시에 한 자원에 접근하지 못하도록 하는 동기화 도구이다. 뮤택스 락은 lock 상태를 표현하는 변수와 락을 거는 acquire() 함수와 락을 해제하는 release() 함수로 구성된다. 어떤 프로세스가 임계 지점에 들어가기전에 acquire() 함수를 호출하여 락을 걸고 임계 지점에서 작업을 다 처리한 후에 release() 함수를 호출하여 다른 프로세스가 임계 구역에 접근할 있도록 한다.

lock = True

def acquire():
    while lock:
        pass
    lock = True


def release():
    lock = False

acquire()
# 임계 구역
release()

세마포어(semaphore)

세마포어는 신호라는 뜻으로 임계 구역 진입전에 wait 신호가 있으면 대기하고 signal 신호가 있으면 임계 구역에 진입한다.

S = 2
def wait():
    S -= 1
    while S < 0:
        pass


def signal():
    S += 1

모니터

세마포어를 사용할 경우 wait 함수와 signal 함수 호출 실수가 있을 수 있다. 모니터는 이런 점을 보완한 동기화 도구이다.