본문 바로가기

Operating System

[Ch 1] Introduction to Operating System

1.1 What Operating Systems Do

컴퓨터 시스템은 크게 4가지 계층으로 나누어 볼 수 있는데, hardware, OS, application program, user이 그것이다.

출처: 교재 Figure 1.1

OS는 여러 user들이 여러 application을 사용할 수 있도록 하드웨어를 제어하는 역할을 한다. 여기서는 user의 관점과 system의 관점으로 나누어 OS의 역할을 살펴본다.

1.1.1 User View

User 관점에서는 우선 사용하기에 편리해야 하며, user가 현재 하고 있는 일의 효율성을 최대화하도록 해야 한다. 마치 user의 프로그램이 컴퓨터의 모든 자원을 독점(monopolize)하고 있다는 착각을 주도록 말이다. 최근에는 스마트폰, 태블릿 등 user가 소통하는 기기가 다양해지는데, 이러한 기기들은 touch screen의 형태로 interface를 제공한다. 또는 음성 인식을 이용하기도 한다. 가전 제품이나 자동차 등의 임베디드 컴퓨터는 상태를 출력하는 등 매우 제한적인 형태로만 user에게 그 형태가 보여지며, 기본적으로는 user의 개입 없이 OS가 돌아가도록 설계되어 있다.

 

1.1.2 System View

OS는 하드웨어와 가장 밀접하게 연관되어 있는 프로그램이며, resource allocator이다. 여기서 말하는 자원이란 하드웨어 자원으로, CPU time, 메모리, 저장 공간, I/O 장치 등이 이에 속한다. 자원들에 대해 여러 요청이 들어왔을 때 OS는 각 프로그램과 user에게 어떤 식으로 자원을 할당해주어야 하는지를 결정해야 한다. 또 다르게는 control program이라고 볼 수 있는데, user 프로그램에서 오류가 발생할 수 있는데 이로 인해 컴퓨터 하드웨어가 잘못 사용되는(improper use) 것을 방지한다.

 

1.2 Computer-System Organization

컴퓨터 시스템은 여러 개의 CPU, 여러 개의 device controller, 이들이 연결되어 있는 공통의 bus, 메모리로 구성된다.

출처: 교재 Figure 1.2

Device controller는 디스크, 오디오 장치 등 특정 종류의 device마다 정의되어 있는 하드웨어인데, 공통적으로 local buffer storage와 register set을 포함한다. Device controller는 주변 장치와 local buffer 간의 데이터 교환을 수행한다.

 

Device driver는 OS 코드로서, 각각의 device controller를 관리한다. Device driver는 각 controller에 알맞게 동작하며, 나머지 OS가 항상 주변 장치를 uniform interface로 접근할 수 있도록 한다.

 

1.2.1 Interrupts

I/O operation을 시작하기 위해 device driver가 device controller의 특정 레지스터에 값을 load한다. 그러면 controller는 이를 통해 어떤 동작을 수행해야 하는지를 알게 되고, 만약 외부 장치로부터 정보를 읽어야 한다면 data transfer를 수행한다. 여기서 data transfer이란 외부 장치로부터 controller의 local buffer로 읽어들이는 것을 말한다. Data transfer이 끝나면 controller는 driver에게 수행이 끝났음을 알려줘야 한다. 그러면 다른 OS나 코드에 의해 입력된 정보가 사용될 것이다. 여기서 controller가 driver에게 data transfer operation이 끝났음을 알려주는 매커니즘이 interrupt이다.

 

1.2.1.1 Overview

Hardware는 CPU에게 system bus를 통해 interrupt signal을 발생시키며, 이것은 OS와 하드웨어가 서로 소통하는 가장 핵심적인 부분이다. CPU는 interrupt 요청이 들어오면, 수행 중인 것을 멈추고 제어 권한을 fixed location으로 넘겨주는데, fixed location은 interrupt를 처리할 수 있는 service routine의 시작 주소이다. Interrupt service routine이 수행을 완료하면, CPU는 아까 멈추었던 곳으로 되돌아와 수행을 계속 이어나간다.

 

Interrupt에는 여러 종류가 있고 그 때마다 처리해주어야 할 service routine이 다르다. 이것을 빠르게 수행하기 위해 메모리의 특정 공간에는 각 interrupt service routine의 시작 주소가 정해져 있다. 이 메모리 공간을 interrupt vector라고 한다. Interrupt의 각 종류마다 고유한 번호가 있고, 이 정보를 바탕으로 알맞는 interrupt vector에 접근한다. 그러면 그곳에 명시되어 있는 interrupt service routine의 시작 주소를 확인하여 control이 넘어가게 된다.

 

Interrupt architecture는 interrupt된 시점의 정보를 저장할 수 있어야 하며, 가장 대표적인 것은 실행하던 주소 값이다. 이 주소 값을 저장해두었다가, interrupt service가 종료되면 다시 이 정보를 바탕으로 실행을 기존 주소에서 이어나갈 수 있어야 한다.

 

1.2.1.2 Implementation

CPU 하드웨어는 interrupt-request line을 명령어를 실행할 때마다 확인한다. 만약 신호가 활성화되면 interrupt number를 확인하고 interrupt handler로 넘어가도록 한다. 위에서 설명한 것처럼 interrupt number가 interrupt array(=vector)를 접근하는 index가 된다.

 

현대의 interrupt 처리 구조는 조금 더 복잡한데, 예를 들어 여러 개의 interrupt가 들어왔을 때 우선 순위를 결정하는 것이나 특정 interrupt에 대해서는 조금 더 미뤄두었다가 처리하는 것들을 위해서이다. 이를 위해 별도의 interrupt-controller hardware를 둔다. Maskable, nonmaskable로 구분되는데, nonmaskable의 경우 메모리 오류와 같이 치명적인 하드웨어 오류 등으로 인해 즉시 처리되어야 하는 것들, maskable은 중요한 명령어의 처리를 위해 미뤄졌다가 처리될 수 있는 것들이다. 

 

1.2.2 Storage Structure

프로그램이 돌아가는 메모리는 main memory이며, DRAM이라는 반도체 기술에 의해 구현된다. 하지만 RAM은 volatile memory여서 전원이 꺼지면 정보가 날아간다. 전원이 켜지자마자 실행되는 bootstrap 프로그램은 EEPROM과 같은 non-volatile 메모리에 저장되어 있다. 이것은 속도가 느리기 때문에 자주 접근되지 않는 static program 코드를 저장하기 위해 사용된다.

 

폰 노이만 아키텍처에서 명령어가 메모리로부터 fetch되어 instruction register에 저장된다. 그 후 명령어 decode 과정을 거치고, 이 때 명령어 연산에 사용될 operand를 읽어온다. 명령어가 실행된 다음에는 다시 그 결과가 메모리에 저장될 것이다.

 

이러한 모델에서는 기본적으로 모든 데이터와 코드가 main memory에 저장되어 있는 것을 가정하지만, 실제로는 물리적 한계로 불가능하다. 그래서 메모리는 계층적 구조로 되어 있으며, 아래로 갈수록 저장 공간의 크기가 더 커지며 non-volatile한 특성을 갖는다.

출처: 교재 Figure 1.6

프로그램들이 main memory로 load되기 전까지는 더 하위 계층의 메모리에 저장되어 있다.

 

1.2.3 I/O Structure

1.2.1에서 설명한 interrupt-driven I/O가 적은 양의 데이터를 이동시키는 I/O 장치에 대해서는 적절하지만, 메모리 계층의 하위에 위치한 장치와의 데이터 교환은 훨씬 그 양이 많다. 이 때는 DMA(Direct Memory Access) 방식이 사용된다. 처음에 CPU는 buffer, pointer, counter를 설정하고, device controller가 CPU의 중간 개입 없이 main memory로 block 단위의 데이터 전체를 모두 이동시킨다. CPU로의 interrupt는 byte 단위가 아닌 block 단위로 일어난다. 이러한 방식에서는 I/O operation과 CPU의 다른 연산이 병렬적으로 수행될 수 있기 때문에 보다 효율적이다.

 

1.4 Operating-System Operations

컴퓨터가 처음 켜지면 bootstrap 프로그램이 수행된다. Bootstrap 프로그램은 non-volatile memory에 저장되어 있고, OS 코드를 main memory에 load하여 수행될 수 있도록 한다. OS 코드가 수행되면 event가 일어나기를 기다린다. Event란 I/O 장치에 의한 hardware interrupt일수도 있고, division-by-zero나 invalid memory access와 같은 명령어 오류에 의한 software-generated interrupt일 수도 있고, 또는 사용자 프로그램에 의한 OS 처리 요청인 system call에 의한 것일 수도 있다.

 

1.4.1 Multiprogramming and Multitasking

OS는 여러 개의 프로그램이 동시에 실행되도록 지원한다. 이러한 multiprogramming에서 실행 중에 있는 프로그램을 process라고 부른다. Multiprogramming이 가능하도록 하기 위해서 OS는 여러 개의 프로세스가 동시에 메모리에 올라가 있도록 한다. OS에 의해 하나의 프로세스가 CPU에서 돌아가다가, I/O operation을 기다린다면 다른 프로세스로 switch하여 실행을 이어간다. 이러한 방식으로 CPU가 idle 상태에 놓이지 않도록 한다.

 

여러 개의 프로세스가 동시에 메모리에 올라가 있도록 하기 위해서는 memory management가 필요하며, 여러 개의 프로세스가 동시에 준비가 완료되었다면 그 중에서 어떤 프로세스부터 실행시킬지를 scheduling해야 한다. 이러한 topic들에 대해서는 이후 chapter들에서 보다 구체적으로 다룬다.

 

1.4.2 Dual-Mode and Multimode Operation

Incorrect/malicious 프로그램에 의해 다른 프로그램이 잘못 동작하면 안 되기 때문에, os 모드에서의 실행과 user 모드에서의 실행을 구분할 필요가 있다. 이는 컴퓨터 하드웨어 설계에서 고려되며, mode bit이 존재한다. Mode bit은 0(kernel), 1(user)의 값으로 모드를 구분한다.

출처: 교재 Figure 1.13

User 프로그램에서 system call로 OS의 서비스를 요청한다면 위 그림과 같이 mode bit이 바뀌게 되고, 다시 user 프로그램으로 돌아올 때도 그러하다. Trap이나 interrupt가 발생하면 하드웨어에 의해 mode bit이 바뀌게 된다.

 

명령어 중 일부는 privileged instruction으로 지정되어 있어 오직 kernel mode일 때만 실행될 수 있고, user mode에서 접근을 시도할 경우 illegal instruction으로 판단해 trap을 발생시킨다. Privileged instruction의 예시는 I/O control, timer management, interrupt management 등이다.

 

1.4.3 Timer

OS는 CPU에 대한 control을 가지고 있어야 하는데, 예를 들어 user program이 무한 루프에 빠지면 안 되기 때문이다. 이러한 맥락에서 timer를 사용하여 일정 시간이 지나면 interrupt를 허용하도록 한다. Timer의 구현은 clock과 counter를 이용한다. Timer interrupt를 처리할 때 OS는 치명적인 오류가 발생했는지 아니면 프로그램에 더 시간을 줄지를 판단한다. Timer setting도 privileged instruction이다.

 

1.5 Resource Management

1.5.1 Process Management

Process는 실행 중인 프로그램인데, 여기서 program과 process의 개념이 구분된다. Program은 파일이나 디스크에 저장되어 있는 passive entity이며, 이에 반해 process는 active entity이다.

 

OS가 process management를 위해 해야 할 일은 다음과 같다. User/system process의 생성과 소멸을 담당한다. 여러 개의 process, thread들을 CPU 상에 scheduling한다. Process를 중간에 멈추거나 실행을 이어나간다. Process synchronization, communication 기능을 지원한다.

 

1.5.2 Memory Management

Main memory는 컴퓨터 시스템의 동작에 있어 중심적인 역할을 수행하는데, 프로그램의 명령어들이 저장되어 있는 곳이자 데이터를 읽고 쓰는 곳이기도 하다. 또한 CPU utilization의 효율성, speed of response to user 등의 목적을 위해 여러 프로그램이 동시에 메모리에 올라와 있어야 하므로, memory management가 필요하다.

 

OS는 어느 영역의 메모리가 어느 프로세스에 의해 이용되는지를 추적한다. 메모리 공간을 필요에 따라 allocate/deallocate한다. 프로세스의 어떤 데이터를 메모리로 가져올지 혹은 밖으로 내보낼지를 결정한다.

 

1.5.3 File-System Management

 

1.5.4 Mass-Storage Management

 

1.5.5 Cache Management

일반적으로 cache, CPU, register 간의 data transfer은 전적으로 하드웨어에 의해 구현되나, 디스크와 main memory 간의 data transfer은 OS가 control한다. Cache에서 그러하듯, 여기서도 역시 data coherency를 고려해야 한다.

1.5.6 I/O System Management

OS는 각 외부 장치의 특성을 감춰야(hide) 한다. 이를 위해 device-driver의 general interface를 제공해야 하고, 각 hardware device에 specific한 driver를 가지고 있어야 한다.

 

Reference

A. Silberschatz, Operating System Concepts 10th ed, WILEY (2019) Ch 1