Post

운영체제 - 컴퓨터 시스템(2)

boot

저번 글에선 OS를 naive하게 설명했습니다. 다시, OS를 간략하게 말하면 사용자 application과, 시스템 서비스를 연결시켜 주는 항상 실행되고 있는 프로그램이라고 이야기 하면 이해하기 편해보입니다. 컴퓨터를 킵니다. 이 행위를 부팅(booting)이라고 하지 않나요? 먼저 비휘발성 메모리 (ROM)에서 운영체제를 실행하도록 하는 명령어를 읽어서, 메모리에 올립니다. 이렇게 맨 처음, 컴퓨터를 켜고, 운영체제를 메모리에 올리는 과정을 booting이라고 합니다. 메모리에 명령어가 올라갔으니, CPU는 이를 차례로 수행합니다. 운영체제를 깨운다고 볼 수가 있겠네요. 이러한 명령어의 집합을 bootstrap program이라고 합니다. bootstrap 프로그램의 명령어가 다 끝난다면, 부팅 소리가 와 함께, 맨 처음에 보는 컴퓨터 화면을 볼 수가 있습니다. 축하합니다. 이제 운영체제 커널이 메모리에 올라갔습니다! 여기서 알 수 있는 사실은, 운영체제도 결국 하나의 프로그램이라는 것입니다. 즉, 컴퓨터의 전기 신호에 따라, 제일 먼저 켜지고, 제일 마지막으로 꺼지는 제일 중요한 프로그램이라는 것이죠. 이를 깨우는 것을 booting이라고 합니다.

system daemon

축하합니다! 이제 컴퓨터를 켰습니다. 카카오톡을 키고, 웹 브라우저를 킨다고 가정해보겠습니다. 하지만 웹 브라우저를 키는 동안, 네트워크 통신은 지속되어야 합니다. 이렇게 백그라운드에서 실행되고 있는 프로그램을 시스템 데몬(deamon)이라고 합니다. 이러한 데몬은 거의 항상 메모리에 상주합니다.

OS

OS는 사용자 application과 시스템 서비스를 연결해주는 프로그램이라고 했습니다. 시스템 서비스란 하드웨어에게 명령을 내리거나, 신호를 기다리거나, 메모리에 접근하거나 등등.. 하드웨어와 연관된 작업 및 등등을 해결해주는 서비스라고 보면 될 듯 합니다. 즉, 사용자가 명령어만 잘 내린다면 이를 CPU(hardward)에게 전달하고, I/O device에도 잘 연결해준다는 것이죠. 우리는 직접 하드웨어아 소통하는 것이 아닌. 운영체제를 통해서 hardware와 소통합니다.

kernel과 shell

운영체제는 두 가지로 나뉩니다. kernel과 shell으로 말이죠. shell은 껍데기입니다. kernel은 핵입니다. 우리는 운영체제의 껍데기와 소통(명령)하고, 주어진 명령을 수행하는 부분은 kernel입니다. 즉, shell은 user interface입니다. shell을 통해, 명령어를 지시하고, kernel이 핵심을 수행합니다. 즉, kernel이 우리가 일반적으로 이야기하는 운영체제입니다.

image

제 컴퓨터에 설치 된, 자바의 버전을 확인하기 위해 cmd에서 java –version 명령을 통해 확인하였습니다. cmd를 command line interface라고 합니다. 이 또한, shell의 일종입니다.

hardward과의 소통

이제 하드웨어와 소통하는 방법에 대해 알아봅시다. image

하드웨어는 각자의 controller를 가지고 있습니다. 각 하드웨어에서 발생한 전기 신호를 시스템 버스를 통해 전달합니다.

키보드를 예시로 들어봅시다. 키보드의 A를 눌렀습니다. 이를 하드웨어가 전기신호로 받아들입니다. 운영체제의 device driver는, 각 hardware의 컨트롤러를 관리합니다. 하드웨어 컨트롤러는 local buffer(임시 저장소라고 생각하면 됩니다)를 갖습니다. 받아들인 전기 신호가 이곳에 저장됩니다. 운영체제의 device driver는 local buffer에 있는 data를 system bus를 통해, CPU에 전달하기도 하고, 반대로 CPU의 data를 local buffer에 전달하기도 합니다. 또한, 우리가 마우스와 스피커를 동시에 사용할 수 있는 것처럼, CPU도 하드웨어이기에, CPU와 우리가 접하는 I/O device는 동시에 실행 가능합니다.

즉 하드웨어 신호를, CPU에게 전달하는데 이러한 과정에도 운영체제가 관여한다는 것입니다.

interrupt - hardware interrupt

하드웨어에서 전기 신호를 받아서, CPU에게 전달했습니다. 현대의 컴퓨터는 병렬 처리를 지원합니다. 이것이 현대 컴퓨터의 근간입니다. 근데 만약 CPU가 어떤 작업을 하고 있다면 어떻게 해야 하나요? 병렬 처리를 지원해야 하는데, 하던 것을 마무리할때 까지, 하드웨어 data에게 기다리라고 할 수는 없습니다. 왜냐하면 작업이 엄청 오래걸린다면, 전기 신호는 계속 기다려야 하는 것이죠. 이는 병렬성을 위반합니다. 이 때, CPU에게 잠시 하던 것을 멈추고, 다른 작업을 하라고 보내는 신호를 interrupt라고 합니다. 방해하다는 말이라서 좋은 의미는 아니라고 처음엔 저도 생각했습니다. 하지만 단지 하나의 신호일 뿐입니다.

interrupt 신호를 받으면, CPU는 각 신호에 알맞은 interrupt service routine(ISR, 하나의 명령어 집합이자, 프로그램입니다. 또한 interrupt handler도 같은 말입니다.)를 수행합니다. ISR은 운영체제 내부에 미리 정의되어 있습니다. interrupt vector에 ISR 명령어의 주소가 담겨 있고, CPU는 interrupt 신호를 감지하면 자동으로 interrupt vector로 점프하도록 설계되어 있습니다. CPU는 interrupt vector에서 내가 받은 interrput 신호에 해당하는 ISR의 주소를 찾고, ISR을 수행합니다.

위와 같은 상황을 hardware interrupt라고 합니다. 하드웨어에서 오는 전기 신호를 받아들이고, 이는 언제 일어날 지 모르기에, 비동기적 (asynchronous) interrupt라고도 합니다.

interrupt - software interrupt

그렇다면 software interrupt도 있지 않을까요? software interrupt는 user가 잘못된 명령을 내렸을 때, 이를 catch하고 CPU에게 의도적으로 interrupt를 보내 지금 하던 작업을 멈추고, ISR을 수행하도록 하는 것을 software interrupt라고 합니다. 대표적으로, 0으로 나누었을 때, 작업을 멈추고 zerodivisionerror를 내는 것입니다. 이러한 software interrupt를 exception 혹은 trap이라고 합니다. (엄밀히 말하면 조금 차이가 있지만 일단은 이해하고 넘어가면 될 듯 합니다.) 이는, instruction의 수행에 맞춰서 작동하기에, synchronous(동기적) interrupt라고도 합니다.

링크 : trap과 exception의 차이

이렇게 운영체제는 interrupt 기반으로 작동합니다. interrupt가 전달되고, 원래 하던 작업으로 돌아와야 하지 않나요? 따라서, 운영체제는 레지스터에 PC(program counter. personal computer가 아닙니다! 현재 실행되고 있는 instruction의 메모리 주솟값입니다.)값을 저장해둡니다. 이를 통해서 interrupt routing이 끝난 후, 다시 하던 작업으로 돌아와 작업을 진행합니다.

image

순서를 나타내보자면,

1
2
3
4
5
6
1. CPU가 작업중임.
2. I/O request가 필요한 상황에, 운영체제의 device driver는 device는 I/O 요청을 시작함. 이 때, CPU는 기존의 작업 중.
3. I/O request가 끝나면, OS의 device driver가 CPU에게 interrupt 신호 전달. 
4. device controller의 local buffer에 저장된 data가 system bus를 통해 이동하고, CPU는 기존의 작업을 멈추고, ISR 수행.
5. CPU는 I/O data를 메모리에 올리고, 작업함(ISR). 기존의 하던 작업의 메모리 주소를 레지스터에 저장해둠.
6. 다 끝난 후, 저장해둔 기존의 작업 주소로 돌아가서 작업 진행.

CPU와 I/O device는 각각 병렬적으로 작업함을 다시 한 번 확인할 수 있습니다.

image

하지만 이는, 중간에 OS가 CPU에게 ISR을 수행하는 명령을 합니다. 즉 CPU를 거쳐서 메모리에 올리는데, 이는 overhead가 있다는 것입니다. 바로, I/O device에서 메모리로 data를 전달하는 것을 DMA(direct memory access)라고 합니다.

모든 작업은, CPU를 통해 거치고, 작업의 내용은 메모리에 존재합니다. 심지어 data를 적재하는 것 또한 CPU를 거쳐야 합니다. 이를 줄이자는 의미가 DMA입니다.

multiprocess architercure

현대 architecture는 거의 multi가 접두사로 붙습니다. 멀티코어, 듀얼코어 .. 등등 많이 들어봤지 않나요? multi의 다른 의미는 하나를 여러개로 분산시킨다는 의미를 이해하고, 왜 이렇게 multi에 집착하는지 생각해봅시다. 제일 큰 이유는 속도라고 생각합니다. 당연지사 하나보다, 두 개가 빠르기 때문입니다. 또한, 분산작업을 의미하기에, 하나에 장애가 생겨도 전체 문제보단 훨씬 낫다는 것입니다. 이러한 multi processor에는 2가지 타입으로 나뉩니다. 이에 대한 의미를 조금 들여다봅시다.

Symmetric Multiprocessing - 모두 같은 기능을 하는 system

image

하나의 processor당 하나의 CPU를 갖는 구조입니다. 즉 CPU가 프로세서와 독립적입니다. 작업을 수행할 때, 하나의 프로세서가 작업하고 나머지 프로세서는 노는 유휴 상태가 생길 수 있습니다. 이러한 문제점을 보완하기 위해 나온 것이 멀티코어 디자인입니다.

image

이렇게 하나의 프로세서(칩)에 CPU를 많이 장착한다면, 하나의 process에 대해 여러 CPU가 연산을 처리하기에, 좀 더 효율적인 연산이 가능합니다. 하지만 이는, 병목 현상을 초래합니다. system bus는 한 번에 하나의 CPU만 이용할 수 있는데, CPU가 시스템 버스의 사용을 두고 싸울 가능성이 있습니다. 즉, 병목 현상을 초래합니다.

Asymmetric Multiprocessing - 각자 다른 기능을 하는 system.

이러한 문제를 해결하기 위해 비대칭적 구조를 알아보겠습니다. 대표적인 예시로 Non-Uniform Memory Access System(NUMA)이 있습니다.

image

각 CPU마다 local memory를 두어 병목 현상을 없애자는 것입니다. 하지만, 나의 local memory가 아닌 다른 memory에 접근할 때는 상대적으로 속도가 느릴 수 있습니다.

Clustered System

그리고, 꼭 하나의 컴퓨터 내부에서 분리하지 말고, 네트워크 시스템을 사용해서 여러 개의 컴퓨터를 하나로 사용하는 방식도 있습니다.

이를 Clustered System이라고 합니다. Clustered System에도 대칭 구조와 비대칭 구조가 존재합니다. 대칭 구조는, 모든 컴퓨터가 같은 기능을 하는 구조입니다.

마무리하며

OS와 interrupt에 대해 알아보았습니다. 다음 글에선 OS의 두 가지 모드에 대해 알아보겠습니다.

CPU 는 메모리에 있는 명령을 읽어 와서 실행하는데, 만일 읽어 온 명령이 소프트웨 어 인터럽트를 발생시키는 int 와 같은 명령이라면 CPU 는 마치 하드웨어 인터럽트 신 호를 받은 것처럼 지금 하고 있던 일을 멈추고, 운영체제 프로그램 내에 포함되어있는 인터럽트 서비스 루틴으로 점프한다. 즉 운영체제 코드가 실행되는 것이다 (그림 2.6). 이 예제의 경우 프린터 서비스 루틴이 실행된다.

하나의 프로세서는 하나의 프로세스를 처리한다. 내부 CPU를 늘려 속도를 증가시킨다.

This post is licensed under CC BY 4.0 by the author.