되자!백엔드개발자

[OS] 2-1: 컴퓨터 시스템 구조&프로그램 실행(1) 본문

CS/운영체제

[OS] 2-1: 컴퓨터 시스템 구조&프로그램 실행(1)

HyunJng 2023. 6. 21. 05:02

앞으로 배울 것에 대한 Overview를 진행했습니다.


컴퓨터 시스템 구조


  • Hard Disk : 하드디스크를 보조디바이스로 보기도 하지만 IODevice로 보기도 한다.
    메모리가 하드디스크에서 읽어들이기도하고 처리 결과를 하드디스크에 저장하기도 하기 때문.
  • device controller: 각각의 IO 디바이스가 가지고 있는 CPU 비슷한 것이다.
    ex) Disk의 내부 통제는 디스크에 붙어있는 device controller가 해준다.
  • local buffer: 각각 IO device의 작업공간이다.
  • Memory : Main CPU의 작업공간. CPU는 메모리에서 읽어서 instruotion을 실행.
  • register: CPU안에 있는 메모리보다 더 빠르면서 정보 저장하는 작은 공간
  • mode bit : 현재 instruction을 보낸 것이 사용자 프로그램인지, 운영체제인지 구분해주는 역할
  • interupt line
  • timer: 특정 프로그램이 CPU를 독점하지 않도록 막는 역할.
  • mode bit
  • DMA controller
  • Memory controller

 

전체적인 동작과정

CPU는 항상 메모리에 있는 instruction을 실행한다. 하나의 instruction이 완료되면 다음 것이 실행되는 형식으로 끊임없이 반복한다.(instruction이란 키보드에서 입력이 들어왔다던지, Disk에서 읽어오라고 요청을 했다던지 등등 지시사항을 말한다)

그런데 instruction 중에 입력 값을 받아서 처리해야하는 등의 앞의 instruction이 끝나야지 실행할 수 있는 것이 있다. 그런 경우 CPU는 Input Device의 device controller에 명령을 내린다.

Input Device가 입력값을 받아서 local buffer에 넣는 과정은 오래 걸리기 때문에 CPU는 Input Device가 수행을 완료할 때까지 기다리지 않고  memory에 있는 가능한 다른 instruction 먼저 실행한다.

💡 CPU는 직접 I/O Device에 접근하지 않는다는 것과 CPU는 계속해서 Instruction을 실행한다는 것을 알 수 있음.

 

그런데 문제되는 상황이 있다. 만약 작동하는 프로그램이 무한루프를 도는 프로그램이라면 어떻게 될까? 그냥 두면 CPU가 instruction을 끝내지 못했기 때문에 다음 instruction을 실행하지 못하게 될 것이다.

이런 문제를 timer이라는 하드웨어를 두어 해결했다.

프로그램이 CPU에 넘겨지기 전에 timer에 시간을 할당한다. 프로그램이 실행 도중 세팅된 시간이 되면 timer가 CPU에게 interrupt를 건다. 그리고 CPU는 매번 하나의 instruction 끝나면 inturupt line을 체크하며 inturrupt 명령이 왔는지 확인한다.

 

프로그램은 I/O디바이스에 직접 접근이 불가능하게 설계됐다. 무조건 OS를 거쳐야 한다. 그래서 프로그램이 I/O 디바이스를 쓰고싶으면 CPU를 OS에 넘겨주고, OS가 I/O 디바이스에 접근하는 형식이다. 위에서 말했듯이IO가 오래걸리니 OS는 요청한 프로그램말고 다른 프로그램에 CPU를 넘긴다.

요청한 프로그램은 I/O 컨트롤러가 요청한 작업이 끝나면 CPU 컨트롤러가 CPU에 interrupt를 걸게된다. 그러면 CPU제어권이 OS에게 자동으로 넘어간다. OS는 지금 Inturupt가 왜 들어왔는지 파악하고, 요청한 프로그램의 메모리 공간에다가 입력값을 카피를 해주고, interrupt 당한 프로그램에 보통 CPU를 다시 주고 할당된 시간이 끝나면 언젠간 키보드 입력이 끝난 프로그램에게 CPU를 준다.

💡 OS도 일종의 프로그램이므로 CPU를 넘겨받아서 실행된다.

 

Mode bit

잘못된 수행으로 다른 프로그램 및 운영체제에 피해가 가지 않도록 instructor을 구분하는 역할.

1: 사용자 모드: 사용자 프로그램 수행 ← 제한된 instruction만 실행
0: 커널 모드 : OS 코드 수행 ← 제한없이 instruction 실행
  • inturrupt나 Exception발생시 하드웨어가 mode bit를 0으로 바꿈
  • 사용자 프로그램에게 CPU를 넘기기 전에 mode bit를 1로 셋팅

I/O명령은 커널모드에서 실행

Timer

CPU를 특정 프로그램이 독점하는 것을 보호하기 위한 역할

정해진 시간이 흐르면 운영체제에게 제어권(CPU)이 넘어가도록 inturrupt를 발생

Device Controller

각 IO장치를 전담하는 일종의 작은 CPU

제어 정보를 위해 controler register, status register이 있음 ← 지시
데이터를 저장하는 local buffer도 가짐 ← 지시에 사용할, 결과인 데이터 담음
  • Device driver : OS 코드 중 각 장치별 처리 루틴을 처리 → software
    • OS는 Device driver에 있는 메뉴얼(코드)대로 작동한다. 메모리 몇번지에 있는 일을 하라는게 적혀있고 그 일으 하고나면 그 다음 페이지의 명령을 실행하고… 반복 ⇒ 이런 전체적인 통제는 OS가 함
  • Device Controller: 각 장치를 통제하는 일종의 작은 CPU → hardware

 

이렇게 되면 CPU가 너무 interrupt를 많이 받는다는 문제가 생긴다.

이런 문제를 해결하기 위해  DMA(Direct Memory Access) Controller 가 있다..

DMA는 말그대로 직접 메모리에 접근할 수 있다는 뜻이다. 원래 메모리에 접근할 수 있는 것은 CPU 뿐이었지만 DMA Controller도 접근할 수 있는 권한이 있는 것이다.

 

DMA controller가 있을 경우 동작과정

I/O Device가 각각의 작업을 끝내면 local buffer에 저장 후에 interrupt를 발생시킨다. 특정 분량이 차면 DMA controller가 CPU대신 I/O 장치들을 local buffer에 있는 내용들을 메모리에 카피하는 작업까지 해준다.

DMA controller 가 없던 기존 설명에서는  I/O Device가 작업을 하며 특정 분량이 찰 때마다 CPU에게 interrupt를 보내고 CPU가 직접 local buffer에 있는 것을 메모리에 Copy했다면, 이런 과정을 DMA controller이 해주고 난 뒤에 한꺼번에 interrupt를 걸어 발생 빈도를 낮추는 것이다.

그러나 CPU와 DMA 가 메모리에 동시 접근하면 문제가 생길 수 있다.

이런 문제를 해결하기 위해 Memory Controller은 그런걸 중지하는, 교통정리하는 역할을 담당한다.

입출력(I/O)의 수행


I/O Device는 운영체제만이 다룰 수 있다. 그렇기에 사용자 프로그램은 I/O를 하려면 운영체제에게 I/O요청(= I/O 함수)을 해야한다. 이런 요청을 시스템 콜(System call) 이라고 한다.

CPU가 어떤 프로그램의 main함수 실행하다가 중간에 내부 함수를 실행하게되면 내부에서 내부 함수에 대한 instruction의 메모리 주소로 jump해서 실행한다. 

그런데 I/O함수(System call)를 호출한다면 이렇게 메모리 주소를 jump하는 식으로는 안된다. 기존에 mode bit가 1이었던 것을 운영체제의 코드라는 의미의 0으로 바꿔줘야하기 때문이다.

입출력 과정

프로그램이 직접 CPU에 함수호출로 interrupt(software 인터럽트, trap이라고 함)를 걸어 인터럽트 벡터의 특정 위치로 이동한다. 그럼 제어권이 인터럽트 벡터가 가리키는 인터럽트 서비스 루틴으로 이동한다. 이 경우 CPU는 다음 instruction을 실행하는 것이 아니라 CPU제어권을 OS에게 준다.

OS는 올바른 요청인지 확인 후 I/O 디바이스를 수행하고, I/O 완료 시 CPU 제어권을 시스템콜 다음 명령으로 옮긴다.(hardware 인터럽트)

인터럽트(Interrupt)


인터럽트를 당하면 register와 program counter을 저장한 후 CPU의 제어를 인터럽트 처리 루틴에 넘긴다.

인터럽트의 종류
  • Interrupt : hardware가 발생시킨 인터럽트
  • trap : software 인터럽트
    • Exception : 프로그램이 오류를 범한 경우
    • System call: 프로그램이 커널함수를 호출하는 경우

인터럽트를 걸을 수 있는 것들은 많은데 그 종류마다 수행해야하는 것이 다를 것이다. 각 장치가 인터럽트를 걸 때 어떤 것을 해야하는지는 OS 코드에 다 정의되어있다. 이 실제 코드를 인터럽트 처리 루틴이라고 부르고, 어떤 코드(함수)로 가야하는지 표시를 인터럽트 벡터에 해둔다.

  • 인터럽트 벡터: 해당 인터럽트의 처리 루틴 주소를 가지고 있음.
  • 인터럽트 처리 루틴(= 인터럽트 핸들러) : 해당 인터럽트를 처리하는 커널 함수.