본문 바로가기
시스템 프로그래밍

Operating Systems(OS) Overview

by sepang 2021. 11. 5.

  Windows, Mac, Linux 등이 OS라는 것은 알고 있었지만 OS가 정확히 무엇인지에 대해 생각해 본 적은 없었다. 중간고사 이후에는 수업에서 OS에 대한 내용을 다룬다. OS overview에서는 OS란?, OS service와 operation, System Call에 대해 살펴보자.

What is an Operating System?

fig 1

  fig 1은 전체적인 컴퓨터 시스템을 나타낸 것이다. 확인할 수 있듯이 4개로 나눠볼 수 있다.

  • Users(사용자): 사람, 기계, 다른 컴퓨터 등에 해당한다. users는 computing problems를 해결하길 원한다.
  • Application programs: 컴퓨터 리소스를 사용하는 users의 computing problems를 해결한다.
  • OS: 다양한 어플리케이션과 사용자 간의 하드웨어 사용을 제어하고 조정한다.
  • Hardware: 기본적인computing resource를 제공한다. ex) CPU, memory, I/O devices

   저렇게 OS에 대해 이해할 수도 있긴 하지만 OS에 대한 보편적인 정의는 없다. '하드웨어를 애플리케이션에 유용한 형태로 변환하는 프로그램'라고도 할 수 있고 '컴퓨터에서 항상 실행되는 커널'이라고 할 수도 있다.

Goals of OS

  어찌됐든 OS가 HW와 프로그램(or 사용자) 사이의 동작들을 조율하는 목적은 무엇일까? 사용자가 프로그램을 실행하여 문제를 보다 쉽게 해결할 수 있는 환경을 제공하고 컴퓨터 시스템을 더 사용하기 쉽게 만들고 또한 효율적이고 안전한 방법으로 컴퓨터 HW를 사용할 수 있게 하기 위해서이다.

What OS Do

  그렇다면 위와 같은 목적을 이루기 위해 OS는 무엇을 할까? 우선 애플리케이션/사용자의 측면에서 살펴보자. 우리가 어떤 워드, 메모장 같은 프로그램을 실행할 때 컴퓨터의 리소스들이 어떻게 활용하는지는 신경 쓰지 않는다. 우리는 단지 편의성, 사용 용이성, 우수한 성능을 원할 뿐이다. 즉 OS는 프로그램 실행 환경을 제공하고 기본 컴퓨터 시스템에 대한 추상적인 view를 제공한다. 프로세서 -> 프로세스/쓰레드, 메모리 -> 가상 메모리 주소 공간, 저장소 -> 파일/폴더처럼 말이다. 

  그럼 시스템의 관점에서는 OS가 리소스 사용을 위해 경쟁하는 많은 애플리케이션&사용자들을 적절히 처리하기를 원할 것이다. 때문에 OS는 리소스 관리자 역할을 하여 컴퓨터 시스템의 다양한 리소스를 관리함으로써 상충되는 요청을 처리하여 효율적이고 공정한 자원 사용을 이룬다. 또한 제어 프로그램의 역할도 하는데, 컴퓨터의 요류 및 부적절한 사용을 방지하기 위해 프로그램 실행을 제어한다.

Operating System Services

  그렇다면 구체적으로 OS가 제공하는 서비스들에 대해 알아보자. 보면 알겠지만 너무나 당연하게 사용해 오던 것들이 모두 OS service였다는 걸 알 수 있다.

  • UI(User Interface): 예를 들면 CLI나 GUI가 있다.
  • 프로그램 실행: 프로그램을 메모리에 로드하고 프로그램을 실행한다. 이후 정상 또는 비정상(오류 표시) 실행종료.
  • I/O 작업: 실행 중인 프로그램에는 파일이나 I/O 장치같은 I/O가 필요할 수 있다.
  • 파일 시스템 조작: 프로그램은 파일이나 폴더의 생성/삭제/읽기/쓰기가 필요하다. 또한 파일을 검색하거나, 목록화, 권한 관리 등도 할 수 있다.
  • Communication(IPC): 프로세스는 동일한 컴퓨터나 네트워크를 통해 컴퓨터 간에 정보를 교환할 수 있다. 예를 들어 공유 메모리나, 메시지 전달을 통해 이를 수행할 수 있다.
  • 오류 감지: 가능한 오류들을 지속적으로 인식한다. 오류는 CPU, 메모리, HW, I/O 장치, 사용자 프로그램에서 발생할 수 있다. 정확하고 일관된 컴퓨팅을 보장하기 위해 이러한 오류들에 대해 적절한 조치를 취한다.

  그리고 리소스 공유를 통해 시스템 자체의 효율적인 운영을 보장하기 위한 또 다른 OS 기능 세트도 존재한다.

  • 자원 할당: 여러 사용자나 작업이 동시에 실행되는 경우에 각각에 리소스를 할당해야 한다.
  • Accounting: 어떤 사용자가 얼마나 많은 리소스를 사용하는지 추적한다.
  • 보호 및 보안: 보호에는 시스템 리소스에 대한 모든 액세스가 제어되는지 확인하는 것이 있고, 보안은 사용자 인증이나 잘못된 접근 시도로부터 외부 I/O 장치를 보호하는 것 등이 있다.

How Computer Systems Work

  OS의 목적이 '컴퓨터 시스템을 '잘' 동작시키기'라는 것을 알았다. 이번에는 컴퓨터 시스템이 어떻게 동작하는지 살펴보자. 

Computer System Organization

fig 2

  fig 2는 컴퓨터 시스템을 다른게 나타낸 것이다. 하나 이상의 CPU, 특정 장치 유형을 담당하는 장치 컨트롤러(disk controller, USB controller, ...)는 공유 메모리에 대한 액세스를 제공하는 공통 버스(common bus)를 통해 연결된다. 이는 동일한 통로를 가진다는 것이고, 때문에 한번에 하나의 component만 버스를 이용할 수 있다. 그러므로 CPU와 장치 컨트롤러들은 memory에 접근하기 위해 서로 경쟁해야 한다는 의미이다.

  각 장치 컨트롤러에는 로컬 버퍼(파란색 사각형)라는 것이 있는데 I/O 장치나 memory에서 오는 정보들을 잠시 저장하는 용도이다. 장치와 장치 컨트롤러 사이의 정보가 오가는 것을 I/O operation이라고 한다. 그리고 OS는 I/O operation을 처리한다. 예를 들어보자. 사용자가 키보드에 어떤 것을 입력(노란색 사각형)하고 이것이 장치 컨트롤러에 저장이 된다(I/O operation). 그리고 OS는 CPU를 이용해서 로컬 버퍼에 저장된 정보를 메모리에 저장하게 한다. 이렇게 되면 다른 애플리케이션이 해당 정보를 사용할 수 있게 된다. 반대로 메모리에 저장되어 있는 정보를 하드디스크에 올리는 과정도 생각해 볼 수 있을 것이다.

  그러면 시야를 옮겨서 CPU(OS가 제어)관점에서는 I/O operation이 종료되는 것을 알아야 메모리에 정보를 옮기든가 할 수 있을 것이다. 어떻게 알아낼 수 있을까? polling(or programmed I/O) 방법은 CPU가 계속해서 I/O operation이 진행 중인지 확인하는 것이다. 하지만 확인하는 동안 CPU는 다른 컴퓨팅 작업을 할 수 없을 테니 딱 봐도 효율적으로 보이진 않는다.

  때문에 다른 방식인 interrupt라는 것을 사용하는데. 장치 컨트롤러가 I/O operation이 종료되면 interrupt(전기적 신호)를 발생시켜서 CPU에게 I/O operation의 종료를 알린다. 그러면 interrupt 이전에는 CPU는 다른 작업을 할 수 있는 것이다.

Interrupt Handling Process

fig 3

  interrupt는 중요한 개념이므로 좀더 자세한 과정을 확인해 보자.

  1. 시스템은 interrupt 발생 전까지 CPU의 현재 상태를 유지한다. 즉 핸들링 이후에 다시 돌아오기 위해 메모리에 현재 레지스터 값과 interrupt 발생직전 주소(PC)를 저장한다.
  2. 이후 HW가 interrupt를 발생시키면 해당 interrupt를 해결하기 위한 interrupt service routine(or interrupt handler)로 점프한다. 많은 interrupt handler들이 존재하는데 이것들은 interrupt vector라는 곳에서 관리가 된다.
  3. interruput 처리가 끝나면 레지스터를 복원하여 interruput 발생 전 상태로 돌아간다.

  추가적으로 HW intterupt 말고 SW interrupt라는 것도 있는데 이는 명령어 실행에 의해 발생하는 interrupt이다. 예를 들면 소프트웨어 오류(ex. 0으로 나누기), 인증되지 않은 데이터 접근, 시스템 서비스 요청 등이 있다.

fig 4

  fig 4에서 CPU는 다른 프로세스를 실행하고 있다가 I/O 장치의 전송이 끝났을 때 전기적 신호가 발생하여 그때만 잠시 intterupt를 처리하는 것을 확인할 수 있다.

Multiprogramming

fig 5

  OS의 가장 중요한 측면 중 하나는 여러 프로그램을 실행할 수 있다는 것이다. 다중 프로그래밍은 이를 위해 사용되는 실행 모델이다. fig 5처럼 4개의 프로세스(※ 프로그램이 실행되어 메모리에 올라오면 프로세스라고 함)가 메모리에 로드되고 우선 job1이 cpu를 점유 중이라고 하자. job1 실행 도중에 I/O operation이 발생하면 이때 OS는 다른 프로세스를 처리한다. 하지만 job1이 별다른 I/O operation을 가지지 않으면 job 4에서 무엇을 입력해도 그에 대한 응답을 빠르게 받을 수 없을 것이다.

Multitasking

  이러한 단점을 보완한 것이 바로 멀티 태스킹(시간 공유)이다. 멀티 태스킹은 CPU가 프로세스를 매우 빠르게 전환하여 사용자가 실행 중인 각 프로세스와 상호 작용할 수 있도록 하는 방법이다. OS는 각 프로세스에게 time slice라는 것을 할당해 준다. 이는 각 프로세스가 CPU를 사용할 수 있는 시간을 의미한다. fig 5에서 각 프로세스에게 10ms라는 time slice를 부여하면 CPU는 10ms마다 처리하는 프로세스를 전환한다. 이것이 사용자에게는 여러 프로그램이 동시에 동작하는 것처럼 인식되는 것이다. 만약 job4에 어떤 입력값을 줬으면 40ms안에는 이에 대한 응답을 받을 수 있다.

 

System Call

Protecting the System

  시스템 콜에 대해 이야기하기 전에 시스템 보호에 대해 알아보자. OS는 어떻게 사용자 애플리케이션이 시스템에 해를 끼치는 것을 방지할 수 있을까? 예를 들어 어플리케이션이 디스크 드라이브에 직접 액세스 하거나, interrupt handler를 재정의한다거나, HLT(halt, 명령실행을 중지하고 프로세서를 정지상태로 만듦) 명령을 실행한다든가 하는 경우에 말이다.

  위 같은 상황을 방지하기 위해 CPU는 'user mode'나 'kernel mode'에서 작동한다. 이 같은 dual-mode operation을 이용하여 OS가 OS 자체 및 기타 시스템 구성 요소를 보호할 수 있는 것이다. 즉 중요한 것과 일반적인 것을 분리해 놓았다고 생각하면 되겠다. 모든 권한이 필요한 명령어는 커널 모드에서만 실행 가능하다. 'mode bit'(HW에서 제공)를 통해 시스템이 실행 중인 mode를 구별할 수 있다.

  최신 CPU는 2개 이상의 모드(multi-mode operation)를 지원한다. 게스트 VM을 위한 VMM(Virtual Machine Manager)이 그 예시인데, 각 VM은 메모리 접근을 위한 공간이 제한된다.

fig 6. VMM

Privileged Instructions

  그럼 권한이 필요한 명령에는 어떤 것들이 있을까? 당연히 신중하게 실행해야 하는 명령들일 것이다.

  • Direct I/O access: ex) IA-32의 IN/OUT 명령어
  • Accessing/manipulating system register: ex) 제어 레지스터나 interrupt vector
  • Memory state management: ex) 페이지 테이블 업데이트, 페이지 테이블 포인터, TLB 로드 등

  그런데 사용자 모드에서 애플리케이션을 사용하는데 권한이 필요한 명령어가 실행되어야 할 때는 예외가 발생될 수 있다.

Interrupt vs Exception

  좀 전에 interrupt에 대해 다뤘었다. 그때 HW가 interrupt를 발생시킨다고 했었는데 끝에 SW interrupt도 있다고 하였다. 이것이 바로 Exception이다. SW interrupt보단 통상적으로 Exception이라고 말한다. 그러므로 interrupt는 그냥 HW interrupt라고 생각하자.

  먼저 Exception에 대해 알아보자. 좀전에 "명령어 실행에 의해 발생하는 interrupt이다. 예를 들면 소프트웨어 오류(ex. 0으로 나누기), 인증되지 않은 데이터 접근, 시스템 서비스 요청 등이 있다."라고 했었다. 그러므로 interrupt처럼 처리된다. 그리고 CPU가 명령어를 실행할 때 발생하므로 동기적이다. 또한 Exception은 Trap, fault 두 가지로 나눌 수 있다.

  • Trap: 응용 프로그램이 의도적으로 발생시키는 것이다. 그러므로 정상적인 동작이고 이것을 바로 시스템 콜이라고 한다.
  • Fault: 의도하지 않은 Exception이다. 때문에 비정상적인 동작이다. 주로 에러나 잘못된 접근이다.

  interrupt는 HW 장치에서 생성되고 기계가 발생시키므로 비동기적으로 발생한다.

  최신 OS는 interrupt(exception 포함)-driven이라고 하는데 사용자 모드에서 커널 모드로의 전환은 intterupt나 exception을 통해 수행되기 때문이다.

Transition from User to Kernel Mode

  그럼 사용자 모드에서 커널 모드로 넘어가는 과정을 알아보자.

  첫 번째 방법은 interrupt에 의한 것이다. 멀티 태스킹에 이용되는 Timer HW를 예로 들어보자. 커널 모드에서 OS는 일정 시간 후에 interrupt를 생성하도록 타이머를 설정한다. 사용자 모드에서 응용 프로세스(프로그램이 메모리에 올라왔을 때라고 했었다)는 CPU를 계속 사용하고 있다. 이후 타이머가 만료되면 타이머가 타이머 interrupt를 생성하여 커널 모드로 전환한다. 이때 OS는 프로세스에 대한 결정을 내릴 수 있게 된다.

  두 번째 방법은 system call(시스템 콜)에 의한 것이다.

fig 8. systeml call

system call은 OS에서 제공하는 서비스에 대한 프로그래밍 인터페이스이며 일반적으로 고급 언어(C/C++)로 작성된다. 직접 시스템 콜을 사용하는 대신 high-level의 API(Application Programming Interface)를 통해 프로그램에서 주로 접근한다. 흔히 볼 수 있는 API들에는 Win32 API, POSIX API, JAVA API 등이 있다. 그러므로 fig 9와 같은 구조를 가진다.

fig 9

Type of System Call

  시스템 콜의 종류는 매우 많다. 몇 가지만 살펴보자.

  • Process control: 프로세스 생성/종료, end, abort, load, execute, ...
  • File management: 파일 생성/삭제, 파일 열기/닫기, 읽기, ...
  • Deivce management: request/release device, read, write, ...
  • Information maintenance: get/set time or date, get/set system data, ...
  • Communications: create/delete communication connection, send/receive messages, ...
  • Protection: Control access to resources, get/set permissions, ...

Example of System call

  fig 10은 한 파일의 내용을 다른 파일로 복사하는 시스템 콜 순서이다.

fig 10

  'Write prompt ot screen", "Open input file", "Close output file", "Terminate normally"등의 시스템 콜들을 확인할 수 있다. 그리고 당연하겠지만 같은 내용의 시스템 콜이라도 OS마다 형식이 상이하다.

fig 11. Windows and Linux System Calls

Standard C Library Example

  좀 전에 직접 시스템 콜을 사용하지 않고 high-level의 API를 통해 접근한다고 했는데 C 예시를 통해 알아보자.

fig 12

  우리가 C로 프롬포트 창에 문자열을 출력하려면 'printf'라는 함수에서 라이브러리 콜이 발생한다. 그리고 이는 'write()'는 시스템 콜을 호출하게 되는 것이다.

System Call Implementation

fig 13

  일반적으로 각 시스템 콜은 고유 번호(시스템 콜 번호)를 가진다. System-call interface는 이러한 숫자에 따라 인덱싱 된 테이블을 유지한다. system-call interface는 OS 커널에서 의도한 시스템 콜을 발생시키고 호출의 상태 및 모든 반환 값을 반환한다.

  fig 13에서는 사용자 애플리케이션이 open()이라는 시스템 콜을 system-call interace에 요청했고 이를 받아서 open()에 해당하는 테이블 항목을 찾아서 해당하는 작업을 수행한 뒤에 결과를 반환한다.

  시스템 콜 호출자는 시스템 호출이 구현되는 방법에 대해 알 필요가 없다. 그들은 그냥 API를 준수하고 OS가 시스템 콜에 대해 수행할 작업에 대해서 숙지하고 있으면 된다. OS interface의 대부분의 세부 사항들은 API에 의해 프로그래머들에게 숨겨져 있다.

System Call Parameter Passing

  종종 시스템 호출 시에 시스템 콜 번호뿐만 아니라 여러 가지 정보(매개변수)를 넘겨줘야 한다. 파라미터의 정확한 정보, 종류, 양은 OS 및 시스템 콜에 따라 상이하다.

  OS에 매개변수를 전달하는 데 사용되는 세 가지 일반적인 방법에 대해 살펴보자.

  • 가장 간단한 접근 방식은 레지스터에 매개변수를 전달하는 것이다. 그러나 경우에 따라 레지스터 개수보다 매개변수 개수가 더 많을 수 있다.
  • 매개변수는 메모리의 블록(or data table)에 저장되고 블록의 주소를 레지스터에 담아 전달하는 것이다. 이 방식은 Linux 및 Solaris에서 사용된다.
  • 매개변수는 사용자 프로그램에 의해 스택에 push 되고 OS에 의해 스택에서 pop 된다.

  fig 14는 두 번째 방법의 예시이다.

fig 14


자료 출처

  • Abraham Silberschatz, Peter Baer Galvin, and Greg Gagne, “Operating System Concepts (10th Edition) - Wiley 2019

'시스템 프로그래밍' 카테고리의 다른 글

I/O Systems and Operations  (0) 2021.11.29
OS Structures & Linux Overview  (0) 2021.11.12
Linkers and Loaders  (0) 2021.11.01
Assemblers (4)  (0) 2021.10.15
Assemblers (3)  (0) 2021.10.15

댓글