본문 바로가기

CS 이론/운영체제

[운영체제 사전 학습] 컴퓨터 시스템 구조, Interrupt 소개와 프로그램 실행

728x90

이번 포스트는 본격적으로 운영체제에 대한 내용을 학습하기 전에, 미리 알아야 할 용어, 물리적 측면의 컴퓨터 용어들, 그리고 각각 어떤 역할을 하는지, 그리고 전반적인 운영체제가 작동하는 Overview 이다. (앞으로 배울 내용들을 하나씩 언급하며 한번 훑는다고 생각하면 된다)

 

해당 포스트 내에 등장하는 

 

Dual-Mode, Interrupt, Sync/Asynchoronus, 프로그램 실행시 Address Space  등에 대해

 

어느정도 이해가 되어 있는 상태로 운영체제 학습이 진행되는 것이 좋은 것 같다. 

사실 내가 정리 + 공부하려고 만드는 포스트들이지만... 이해하기에는 계속 반복하는 방법 밖에 없는 것 같다. 

 

 

(1)  컴퓨터 시스템 구조 (Computer + I/O Device)

 

컴퓨터의 동작은 크게 컴퓨터의 구성요소들과 IO Device (Input Output Device)들의 상호작용으로 이루어진다고 보면 된다. 현대에 들어와서 훨씬 복잡해지고 있다고는 하지만, 기본적인 뼈대를 이루는 구조는 다음과 같다. 

 

(Computer의 Device 들은 좌측 CPU / DMA Controller / Timer / Memory Controller / Memory 이 정도가 대표적이라고 보면 되겠고,  IO Device 들은 우측  Hard-Disk / 키보드, 마우스 / 프린터 / 모니터 등 이 정도가 대표적이라고 보면 될 것이다)

 

컴퓨터 시스템 구조

     1. CPU (Core Processing Unit) 

- 컴퓨터의 중앙 처리 장치(뇌)로, 컴퓨터 시스템을 통제하고 프로그램의 연산을 실행하고 처리한다. 

- 가장 빠른 처리속도를 가지고 있으며, RAM (Memory) 에 적재된 intructions (수행문) 들을 순차적으로 가져와서 수행만한다.

- 중간중간에 내부 Interrupt Lines 를 점검하며 당장 Interrupt(아래 나옵니다) 가 필요한 프로그램이 있는지 점검한다. 

 

      - 관련 개념

   * Interrupt Lines : CPU를 뺏기 위해 올라온 Interrupt 내역들이 잠시 대기하는 곳

   * Register : CPU가 다음으로 실행할 Instruction 의 주소를 가지고 있다. 

   * Mode Bit : 사용자 프로그램의 잘못된 수행으로 다른 프로그램 및 OS에 피해가 가지 않도록 하기 위한 보호 장치 (Dual-Mode)

   * Dual Mode 시스템이란?

> 컴퓨터가 운영되는 시스템 상에서 상태를 두 가지 상태로 두는 시스템을 말한다. 현재 상태를 Mode_Bit 저장 공간에 저장하고 계속 바꾸면서 운영을 하는데,  1: 사용자 모드 (User Mode) 이며,  0: 커널 모드, 모니터 모드 (Kernel Mode)를 말한다.

> Kernel Mode는 OS가 CPU를 점유하고 있는 상태를 말한다. 즉, Interrupt나 Exception 발생하였고, 중요한 instruction, I/O접근 등을 수행해야 하는 상태이다.

 

 

OS를 공부하며 CPU의 정체성에 대해 혼돈이 올 때마다 항상 CPU는 "그냥 Register에 등록된 다음 Instruction 주소를 수행하고, 중간중간에 Interrupt Line 확인밖에 안하는 빠르게 일만하는 친구" 라고 생각하면 좋다. OS가 CPU를 어따 던져놓을지가 문제지, CPU는 정말.. 일만한다. CPU Scheduling 관련해서 OS의 중요한 파트를 이해해야 한다.

 

 

     2. Memory (보통 RAM: Random Access Memory)

- 단기 데이터 Storage 라고도 부르며, 정보에 빠르게 엑세스할 수 있도록 컴퓨터가 실시간으로 사용하는 정보를 적재한다.

- 많은 프로그램들이 사용중일 수록 메모리 사용량이 늘어나며, 더 많은 메모리가 필요하게 된다. 

- Process 전환할 시 이전 작업의 위치 기억, 빠른 전환 등을 생각하면 된다. 

- 메모리 한 공간에는 OS가 점유하고 있고, 메모리에 Loading된 User App과 OS 사이에서 CPU가 번갈아가며 일을 수행하는 방식으로 OS는 동작한다고 보면 된다.

 

       - 관련 개념

      * Memory Controller : 메모리 접근을 관리한다. 특히 중복 접근 등을 방지한다.

 

메모리는 그냥 실행중인 프로그램들 (이를 Process라고 함)이 적재되는 공간을 말한다. OS도 하나의 프로그램으로 항상 Memory에 일정 공간을 점유하고 있고, 운영이란 이 모든 프로그램들 사이에서 CPU를 줬다 뺐었다 하는 과정이라고 봐도 될 듯 하다. Memory Management 의 과정을 앞으로 이해해야 한다.

 

   

      3. DMA Controller (Direct-Memory-Access)

-  CPU와 더불어 유일하게 직접 메모리에 접근할 수 있는 장치이다. (참고로 접근 가능 Memory는 Primary(Executable) Memory 라고 부르며, 다음과 같다: Registers, Cache Memory, Main Memory)

-  CPU와 둘이서 특정 메모리 영역에 접근하면 문제가 발생할 수 있으므로,  Memory Controller의 제어가 필요하다.

-  CPU에는 계속 Interrupt(아래 나옵니다 ^^)가 발생하고, 너무 많이 발생하기도 한다. CPU는 일을 빠르게 수행해야하므로 Interrupt가 많이 발생하면 CPU가 비효율적이게 된다.

따라서 OS가 가져오는 내용을 CPU에게 말해 또 직접 복사시키는게 아니라, DMA가 직접 가져온다. 그러면 복사까지 완료했다고 보고 받게 되는 OS는 이후 프로그램을 다시 준비시켜 이후 Sheduling을 하면 된다. (Interrupt 빈도수를 줄이기 위해 도입되었다고 보면 됨)

 

 

     4. Timer

- 타이머는 오직 특정 프로그램의 CPU 독점을 막기위해서, 스케줄링 관점에서 도입된 장치이다. 

- H/W Interrupt 를 발생시키는 장치 중 하나이다. 

- CPU를 프로그램이 계속 점유할 시, Time-Sharing 을 구현하기 위해 CPU를 뺏어서 다른 프로그램에 할당하기 위한 판단 수단이 된다.

 

 

     5. Device Controller & Local Buffer

- 각 I/O Device 들 까지 CPU가 왔다 갔다 하면서 관리할 수는 없기 때문에, 각 Device 마다 내부를 담당하는 미니 CPU, Memory들이 각각 있는데 이를 Device Controller / Local Buffer 라고 한다

 

       - 관련 개념

      * 제어정보 Register : OS가 Device Controller에게 일을 지시할 때 해당 레지스터를 통해서 지시하게 된다.  

      * Devcie Driver (SW) : 해당 디바이스를 사용하기 위해 필요한 설치 S/W. CPU가 일하던 중 IO가 필요한 Instruction을 만나게 되면 System Call 이 수행되며, OS가 CPU를 가져와서 이 Driver프로그램을 통해 Devcie Controller(HW) 에게 명령을 전달하는 것이다. 

 

 

(2)  Computer Device 들과 I/O Device 간의 상호작용 (Interrupt)

 

여기까지 이해가 되었다면 정말 거의 다 이해한거다 (Overview만). 중요한 부분만 정리해보자면

 

"Memory에는 유저 프로그램들이 적재되어 있고, OS도 따로 적재되어 있다."

"CPU는 이 Memory에 있는 데이터 (instructions)들을 열심히 읽고 수행하는 일밖에 안한다"

"위에서 조금씩 언급된 Interrupt, Address Space(주소공간 뭐시기)가 있는 것 같은데 뭔진 모르겠다" 

 

이거다.

 

그럼 이제 Computer 내부는 뭐 그렇다 치는데, IO Device 들은 어떻게 일하는거고, Computer Device와 무슨 쿵짝을 하는걸까?

자 근데 우선 알고 있으면 좋은 건데, 그냥 [보안상의 이유]라는 측면으로... 외우고 가자.  난 그랬다.

 

 

유저 프로그램은 절대 I/O Device에 직접 접근할 수 없다

 

 

그럼에도 프로그램들은 항상 IO Device에 접근 및 제어를 지속적으로 요구하게 된다.

 

 

지금 이 포스트를 읽고 계신 분이라면, 아무래도 C언어, Java, Python 등 언어를 사용해서 프로그램을 짜보는 경험은 무조건 있으실 것 같다. C언어를 예시로 설명을 하자면, 프로그램을 짜다가 무조건 등장하는 애들이, printf, scanf 등 당장 코딩 1일차에 배우는 프로그램을 만드는데에도 등장한다....

 

 

(이쯤에서 System Call 에 대해 잠깐 알고 넘어가자. 읽어보고 무슨소린지 모르겠으면, 그냥 간단하게 System Call = OS 프로그램에 있는 함수를 실행하는 것이라고 생각하고 그냥 넘어가도 된다)

프로그램을 좀 짜다보면, 유저 프로그램이 호출하는 함수는 크게 3가지로 나뉜다.

1. 내가 직접 짠 자신의 프로그램 함수

2. 사용하는 Library들의 함수

3. 위와 같은 커널 함수이다.

2번 같은 프로그램 내에서 사용하는 Library들의 함수 역시 프로그램내 적재되어 있으므로, 유저 프로그램의 Address Space 중 Code Segement내부에 있는 함수 내용을 사용한다. (아래 자세히 나옵니다) 반면에 3. 커널 함수들은 운영 체제 프로그램의 함수를 호출하는데, 이는 OS 프로그램의 Address Space 내부에 있는 함수 내용을 사용하는 것으로, System Call 이라고 부른다. (말로만 들어도 대충 알겠지만, Kernel 함수는 Kernel Mode에서만 실행할 수 있는 OS 프로그램에 저장되어 있는 함수이다)

 

 

자 어쨌든 다시 돌아와서, 

유저 프로그램은 절대 IO Device 에 직접 접근할수 없지만, 접근을 해야하는 경우는 정말 셀 수 없을 정도로 많다. 그렇다면 유저 프로그램에서 IO Device 를 사용하려면 어떻게 하게 되는가? 프로그램들은 직접 IO에 접근할 수 없는걸 알고 있기 때문에, 

 

 

CPU를 OS에게 넘겨주게 된다

 

 

이와 같이 CPU를  IO 입출력 혹은 다른 Exception 상황에 의해 이를 처리할 수 있도록 CPU를 OS에게 넘겨주는 행위를 Interrupt 라고 한다. 그렇다면 OS는 왜 자신한테 CPU가 넘어왔는지 분석을하게 되고, 그 분석결과  필요한 IO Device Controller 한테 "야 니 Device로 이거 해와!" 라고 명령을하게 된다. 이게 일반적으로 앞으로 [I/O가 일어난다] 라고 하면 발생하는 과정이라고 보면 될 것이다.  (CPU 관점에서는 매우 오래 걸리는 작업이므로, 다른 프로그램한테  CPU를 넘겨주게 된다. 하지만 항상 그런 것은 아니고 Interrupt 종류 측면에서 나뉘게 되는데,  이는 앞으로 차근차근 알아가보도록 하자)

 

 

어쩄든 IO 입출력을 하는 사이에 CPU는 여전히 매우 빠른 속도로 다음일들을 빠르게 처리하게 된다.  그러다 입출력이 끝나면, Device Controller가 끝났다고 Interrupt 를 발생시키게 되고, CPU는 다시 OS로 넘어가게 된다. (이 때 Device 의 메모리 역할을 하는 Local Buffer에서 값을  가져와서 프로그램 주소 공간 메모리에 복사를  해주는데, 이 과정까지는 DMA(위에 나왔습니다. 다시 읽어보세요!) 가 하고 OS에게 CPU가 넘어가게 되는데, 이 역시 Interrupt 가 발생한 것이다. 

 

 

자 그러면 Interrupt  가 두 번 발생한다는걸 눈치 채셨다면 이제 아래 Interrupt에 대한 설명을 쉽게 이해하실 것이다. 사실 그냥 이름말 알고 넘어가도 될 것 같은데, 이해가 안되셨다면 계속 쭉 읽기를 바란다. (더 자세하게 한번 더 설명한다)

 

 

Interrupt 는 두 번 발생했다.

 

1) 유저 프로그램이 돌다가 System Call 을 하기 위해 (Software Interrupt)

2) Device  Controller가 입출력이 끝났음을 OS에게 알리기 위해 (Hardware Interrupt)

 

 

CPU는 인스트럭션을 순차적으로 수행하면서, 인스트럭션에 따라 수행하는 주소를 계속해서 바꾸게 되며, 내 Program 안에서 하는 일들은 모드 내 Program 메모리 공간 내부에서 주소를 바꾸는 것이다.  하지만 System Call 을 하는 것 즉, OS Program의 함수를 호출하는 것은 단순히 메모리 주소를 바꾸는 일이 아니다.  OS Program 으로 주소 점프를 못하기 때문에 (당연하다. OS 어디에 그 함수가 있는지 어떻게 알겠는가?) IO 입출력이 다음 instruction 이라면 유저 프로그램은 직접 interrupt line 을 세팅하는 instruction 을 실행한다. 그러면 mode_bit = 0 으로 세팅되어 Kernel_mode로 전환이 되고, OS에게 CPU가 넘어가서 interrupt를 분석하기 시작하는데, 이 과정이 위에서 1)이 일어나는 과정이며, Software Interrupt 라고 부른다. (S/W 프로그램들 상에서 발생하기 때문, Trap이라고도 한다)

 

 

IO를 요청한 프로그램은 기다리고 있고, OS는 IO Device Controller에게 일을 시킨 뒤에 다시  CPU를 다음 프로그램에 넘겨주게 된다. 그러다가 IO 작업이 끝나고 Device Controller 가 자신의 Local Buffer 에 요청 값이 들어온 것을 확인하면 Interrupt Line 세팅을 한다. 역시 CPU 제어권은 OS에게 넘어가 Kernel Mode 로 전환이 되고, OS는 "아까 걔구나, 그럼 DMA가 일을 마쳤나?" 하고 확인을 한다. 그 이후 지금 CPU 제어권을 뺏긴 프로그램에게 보통 다시 CPU를 돌려주게 된다. 이 과정이 위에 2)에서 일어나고 한 IO를 마치는 과정이며, Hardware Interrupt 라고 부른다. (H/W 인 Device Controller 가 직접 걸기 때문. 참고로  Timer 가 거는 Interrupt 역시 H/W Interrupt 라고 부른다)  

 

      - 관련 개념

      * Interrupt Vector : OS가 가지고 있는  인터럽트 분석을 위해 인터럽트 사유에 대한 인터럽트 처리 루틴 (ISR) 주소를 말한다.
                                       Device Controller에게 일을 지시할 때 해당 레지스터를 통해서 지시하게 된다.  

      * Interrupt Service Routine(ISR, Interrupt Handler) : 해당 인터럽트를 처리하는 커널 함수의 수행을 말한다.

 

현대 운영체제는 Interrupt 에 의해 운영된다고 보면 된다고 한다. Interrupt 없이는 Kernel mode도, OS의 일도 수행될 수 없기 때문이다.

 

       * IO 입출력 방식  (참고)

동기식 / 비동기식 IO Flow

입출력에는 매우 유명한 두 가지 방식이 있다.

 

1) Synchronous IO (동기) : IO가 끝날 때까지 기다리는 방식.

2) Asynchronous IO (비동기): 해당  Device Controller에게 명령을 해 놓은뒤 (ISR 수행 후)와서 다른 프로그램을 수행하는 방식

 

Synchronous IO 도 CPU가 정말 같이 기다리느냐, 아니면 CPU 낭비를 줄이기 위해 CPU 는 일을 시키느냐에 따라서 방식이 나뉜다. 그렇다면 Synchronous 중 CPU 소모 하는 종류와  Asynchronous IO 와의 차이는 무엇인가?

 

이건 그냥 개인적인 해석이지만, Synchronous 와 Asynchronous는 CPU의 관점에서 나뉘는 건 아닌 것 같다. 그냥 해당 프로그램이 다음 instruction 을 실행하는 것인지, 아니면 해당 입출력이 끝나기 전에는 다음 instruction 을 수행 못하기 때문에 Waiting으로 전환되는 것인지에 차이가 있는 것이고, Synchronous 안에서 CPU는 다른 일을 해도 되는지에 대해서 나뉘는 것 같다. 

(나도 명확하게 구별하지는 못하겠지만, 그래도 관점이 다른 영역이라서 명확한 비교는 어렵다고 판단했다) 

 

동기 비동기에 대해서는 앞으로 지겹도록 많이 들을 것이므로, 그냥 기다린다 만다의 차이로 알고 넘어가면 되겠다.

 

 

2. 프로그램 실행 Flow (Program Execution)

 

 시스템의 구조에 대해서 어느정도 알아봤으니, 이제 운영체제 내에서 프로그램이 실행될 때 무슨 일이 일어나는지, 그 일들이 어떠한 방식으로 일어나는지 확인해보자. (프로그램이 실행된다는 것, Memory에 Loading 된다는 것)

프로그램 실행 후 주소 공간을 할당받고 물리적인 주소를 할당받는 과정

우선 위 그림과 같이 Physical Computer 내의 Disk 공간 내에 있는 프로그램 파일 A, B를 실행하게 되면, OS 는 프로그램의 메모리 주소 공간을 형성시키게 된다 (Logical Memory, Virtual Memory, Addreess Space).  이 메모리 공간안에서 세 종류의 segment를 형성하여 프로그램을 적재시키는데, 이는 다음과 같다. 

 

Stack Segment - return 하여 stack 할 함수(function) 와 지역 변수 (local variable) (R/W 가능)

Data Segment - 전역 변수 및 활용 자료구조 (R/W 가능)

Code Segment - CPU가 직접 실행할 Instruction Codes (W)

 

 

실제 CPU를 점유시킬 수 있도록 하려면 Main Memory 공간에 올려야 하는데, 이를 Memory Loading 이라고 부른다. 이 때 Segment 들은 실제 Physical Memory 와 Swap Area 로 나누어서 적재가 되는데, 이는 모든 데이터를 메모리에 적재해서 메모리 용량을 낭비하기 보단 필요한 정보만 Memory에 로딩하고, CPU에서 점유할 때 Swap Area 에서 꺼내오는 방식으로 활용하여 메모리를 절약하기 위한 방식이다.

 

위 내용 중 System Call에 대해서 다시 한번 생각해보자면, 유저 프로그램이 실행되던 중 System Call 을 발생시켜 커널 함수를 실행하는 것은, Kernel의 주소 공간 중 Code Segement에 있는 커널 함수들을 실행하려는 행위이다. 

이를 생각해보면 유저 프로그램은 자신 메모리 공간 내에 있는 함수를 번갈아 가며 실행하는 행위를 하며, 그 안에서 메모리 주소를 바꾸면서(논리적인 주소를 바꾸는 행위) 진행이 되는데,  Kernel 함수는 아예 다른 주소 공간에 있으므로 불가능하다 (유저 프로그램이 커널 함수의 논리적 주소를 어떻게 알겠어!). 그래서 System Call 을 통한 Mode Change를 한다는 것으로 한번 더 이해해보면 되겠다.

 

 

 

모든 출처:

 

1.이화여자대학교 반효경 교수님 운영체제 수업 (14학년도 1학기 수업)

http://www.kocw.net/home/m/search/kemView.do?kemId=1046323 

 

 

운영체제

운영체제는 컴퓨터 하드웨어 바로 위에 설치되는 소프트웨어 계층으로서 모든 컴퓨터 시스템의 필수적인 부분이다. 본 강좌에서는 이와 같은 운영체제의 개념과 역할, 운영체제를 구성하는 각

www.kocw.net

 

2. 서울대학교 홍성수 교수님(RTOS Lab) 운영체제 수업 (S-DS 수업 자료)

 

 

728x90