운영체제(Operating System)는 컴퓨터 하드웨어를 관리하는 소프트웨어입니다. 응용 프로그램이 실행되기 위한 기반을 제공하며 컴퓨터 하드웨어와 사용자 사이에 위치하여 중재자 역할을 수행합니다.
컴퓨터 시스템은 크게 네 가지 구성요소인 하드웨어, 운영체제, 응용 프로그램, 사용자로 구분할 수 있습니다. 하드웨어는 중앙 처리 장치(CPU), 메모리, 입출력(I/O) 장치로 구성되어 계산을 위한 자원을 제공합니다. 응용 프로그램은 사용자가 해결하고자 하는 문제를 위해 컴퓨터의 자원을 어떻게 사용 할 지 정의합니다.
운영체제는 다양한 응용 프로그램 간의 하드웨어 사용을 제어하고 조정합니다. 또 컴퓨터 시스템이 하드웨어, 소프트웨어 및 데이터로 구성되어 있다고 생각할 때 운영체제는 이 자원을 적절하게 사용할 수 있는 방법을 제공한다고 생각할 수 있습니다.
사용자의 관점에서 운영체제의 역할은 인터페이스에 따라 달라집니다. 많은 사용자들은 모니터, 키보드, 마우스로 구성된 PC 앞에서 작업합니다. 이 때 컴퓨터 시스템은 사용자가 자원을 독점하여 수행하고자 하는 작업을 최대화할 수 있도록 하는 것이며 이러한 관점에서 운영체제는 사용의 용이성을 위해 설계되었다고 볼 수 있습니다.
시스템 관점에서 운영체제의 역할은 하드웨어와 가장 밀접하게 연관된 프로그램입니다. 따라서 운영체제를 자원 할당자(Resource Allocator)로 볼 수 있습니다. 문제를 해결하기 위해 요구되는 시스템 자원들(CPU, 메모리 공간, 저장장치 공간, 입출력 장치)들을 관리하는 관리자 역할을 운영체제가 수행합니다. 여러 프로그램에서 같은 자원에 대하 요청이 존재할 수 있으므로 운영체제는 효율적으로 어떤 자원 요청에 자원을 어떻게 할당할지 결정합니다.
컴퓨터 시스템에는 여러 가지 입출력 장치와 사용자 프로그램이 존재합니다. 이러한 장치와 프로그램들이 올바르게 동작할 수 있도록 운영체제는 각 장치와 프로그램을 제어하는 제어 프로그램(Controll Program)의 역할을 수행합니다. 특히 운영체제는 입출력 장치의 제어와 작동에 깊이 관여하는 특성이 있습니다.
일반적으로 운영체제에 대한 적합한 정의는 따로 존재하지 않으나, 효율적이고 유용한 컴퓨팅 시스템을 만들기 위한 문제를 해결하는 합리적인 방법으로 볼 수 있습니다. 사용자의 문제를 해결하기 위해 컴퓨터 하드웨어가 사용되나 오직 하드웨어만으로는 사용하기 어렵기 때문에 응용 프로그램을 작성하여 하드웨어를 제어합니다. 이러한 응용 프로그램에는 입출력 장치 제어와 같이 대부분의 프로그램에서 공통적으로 사용되는 작업이 필요하고, 이러한 작업을 위해 자원을 제어하고 할당하는 일반적인 기능을 운영체제라는 소프트웨어를 통해 제공하는 것입니다.
운영체제에 보편적으로 존재하는 요소(Component)는 컴퓨터에서 항상 실행되는 커널(Kernel)과 쉽게 응용 프로그램을 개발할 수 있게 하는 미들웨어 프레임워크 및 시스템 실행 중 시스템을 관리하는 데 도움이 되는 시스템 프로그램이 포함됩니다.
컴퓨터 시스템의 구성
일반적인 현대 컴퓨터 시스템은 하나 이상의 중앙 처리 장치(CPU)와 버스로 연결된 여러 장치 컨트롤러로 구성됩니다. 각 장치 컨트롤러는 특정 유형의 장치를 담당합니다. 일반적으로 운영체제에는 각 장치 컨트롤러마다 장치 드라이버가 존재하여 장치 컨트롤러의 동작과 장치에 대한 인터페이스를 제공합니다.
일반적인 컴퓨터 작업은 다음과 같은 과정을 거칩니다.
입출력 작업을 시작하기 위해 장치 드라이버는 장치 컨트롤러의 적절한 레지스터에 값을 적재합니다.
장치 컨트롤러는 이러한 레지스터의 내용을 검사하여 수행할 작업을 결정합니다.
컨트롤러는 장치에서 로컬 버퍼로 데이터 전송을 시작합니다.
장치 컨트롤러는 장치 드라이버에게 작업이 완료되었음을 알립니다.
작업이 읽기 요청인 경우 데이터 또는 데이터에 대한 포인터를 반환하고, 쓰기 요청인 경우 운영체제의 다른 부분에 제어를 넘깁니다.
위 과정이 끝나면 컨트롤러는 장치 드라이버에게 작업을 완료했다는 사실을 알리게 되는데, 이 때 사용되는 것이 인터럽트(interrupts)입니다. 이와 같이 하드웨어에서 발생한 인터럽트를 하드웨어 인터럽트(hardware interrupt)라고 하며, 컴퓨터 하드웨어는 언제든 시스템 버스를 통해 CPU에 신호를 보내 인터럽트를 발생시킬 수 있습니다.
반면 프로그램에서도 인터럽트로 발생시킬 수 있는데, 이 때 발생하는 인터럽트를 소프트웨어 인터럽트(software interrupt)라고 합니다. 주로 예외 상황이나 오류 처리 등에 사용되며, 대표적인 소프트웨어 인터럽트로는 시스템 콜(system call)과 프로세스 간 통신(IPC, Interprocess Communication)이 있습니다.
인터럽트가 발생하면 CPU는 그 즉시 하던 작업을 중단하고, 해당 인터럽트를 처리하는 인터럽트 서비스 루틴(인터럽트 처리 루틴)이 호출되어 해당 인터럽트를 처리하게 됩니다. 인터럽트 서비스 루틴은 인터럽트 핸들러(interrupt handler)에 의해 관리되며, 여러 인터럽트 서비스 루틴을 등록하고, 인터럽트가 발생하면 적절한 인터럽트 서비스 루틴을 실행합니다. 인터럽트는 매우 빈번하게 발생하기 때문에 빠르게 처리되어야 하고, 이를 위해 운영체제에서는 인터럽트 서비스 루틴에 대한 포인터들의 테이블을 사용합니다. 이 포인터 테이블은 보통 하위 메모리에 저장되며, 인터럽트가 요청되면 인터럽트의 정보를 조회하여 인터럽트 번호를 얻고, 인터럽트 테이블의 해당 인덱스에 위치한 인터럽트 벡터를 조회합니다. 해당 인터럽트 벡터에는 발생한 인터럽트에 대한 인터럽트 서비스 루틴의 시작 주소가 저장되어 있어 해당 주소를 이용하여 인터럽트를 처리합니다.
인터럽트가 처리되고 나면 원래 실행 중이던 연산 작업으로 돌아가야 하므로 CPU는 인터럽트가 발생하면 현재 실행 중인 작업의 상태를 저장(컨텍스트 스위칭, Context Switching)합니다. 인터럽트가 처리되면 실행하던 연산 주소를 다시 프로그램 카운터(PC)에 적재한 뒤 원래 작업을 다시 실행합니다.
CPU 하드웨어에는 IRQ라고도 부르는 인터럽트 요청 라인(interrupt request line)이 존재합니다. CPU가 하나의 명령어를 처리할 때마다 IRQ를 검사하여 인터럽트가 발생했는지 검사합니다. 만약 어떤 컨트롤러가 IRQ에 신호를 보낸 것이 감지되면, 위에서 설명한 것처럼 인터럽트를 번호를 읽고 이 번호를 사용해 인터럽트 벡터를 가져와 인터럽트 핸들러 루틴(interrupt-handler routine)으로 이동하여 인터럽트를 처리합니다. 이 과정을 간단하게 정리하면 아래와 같습니다.
raise : 장치 컨트롤러가 IRQ에 신호를 보내 인터럽트를 발생시킵니다.
catch : CPU가 하나의 명령어를 실행하고 나서 IRQ를 검사합니다.
dispatch : 인터럽트 번호를 사용해 인터럽트 핸들러로 디스패치합니다.
clear : 인터럽트를 처리한 뒤 해당 인터럽트를 삭제합니다.
마스크 인터럽트
대부분의 CPU에는 2개의 IRQ가 존재하는데, 하나는 복구가 불가능한 메모리 오류와 같은 이벤트를 위해 예약된 마스크 불가능 인터럽트(nonmaskable interrupt)이며 다른 하나는 마스크 가능 인터럽트(maskable interrupt)입니다.
마스크 불가능 인터럽트(NMI, nonmaskable interrupt)는 무시할 수 없는 인터럽트로, CPU는 마스크 불가능 인터럽트가 발생하면 반드시 처리를 해야합니다. 하드웨어 장애나 소프트웨어 오류로 인한 비정상적인 상황에서 발생하며, 보통 하드웨어 인터럽트와는 달리 별도의 전기 신호를 사용하여 처리됩니다.
마스크 가능 인터럽트(MI, maskable interrupt)는 무시가 가능한 인터럽트로, 마스킹 여부를 이용해 소프트웨어에서 해당 인터럽트를 무시할 수 있습니다. 이를 이용하여 인터럽트를 처리할 때 우선순위를 지정할 수 있습니다. 일반적으로 발생하는 소프트웨어 인터럽트가 마스크 가능 인터럽트에 해당합니다.
CPU는 여러 인터럽트를 빠르게 처리해야 하므로, 인터럽트의 우선순위를 관리하여 처리할 순서를 결정합니다. 이 때, 마스크 불가능 인터럽트는 최우선으로 처리되며, 그리고 하드웨어 인터럽트, 소프트웨어 인터럽트 순으로 처리합니다.
인터럽트를 처리하는 과정에서 인터럽트 서비스 루틴이 실행되는 도중 다른 인터럽트가 발생하는 경우를 중첩 인터럽트(nested interrupt)라고 합니다. 이 때 인터럽트 핸들러는 현재 실행 중인 인터럽트 서비스 루틴을 중단하고, 우선순위가 더 높은 인터럽트 서비스 루틴을 처리합니다.
CPU가 명령어를 실행하기 위해선 먼저 메모리에 명령을 적재해야 합니다. 범용적으로 사용되는 컴퓨터 시스템에서는 프로그램 대부분을 메인 메모리(RAM, random access memory)라 불리는 재기록 가능한 메모리에 적재하여 사용합니다. 이 외에도 컴퓨터 전원을 켤 떄 가장 먼저 실행되는 프로그램인 부트스트랩 프로그램은 운영체제를 적재하며 읽기 전용 메모리(ROM) 또는 플래시 메모리에 적재됩니다.
모든 형태의 메모리는 바이트 형태의 배열을 사용합니다. 각 바이트는 고유의 주소를 가지고 있어 CPU는 이 메모리를 사용해 프로그램 실행을 위한 명령어를 적재(load) 또는 저장(store)합니다.
현대의 컴퓨터 시스템 구조인 폰 노이만 구조의 컴퓨터 시스템은 메모리로부터 명령어를 인출(fetch)하여, 그 명령어를 명령어 레지스터(instruction register)에 저장합니다. 그리고 명령어를 레지스터로부터 읽고 명령어에 필요한 피연산자를 메모리로부터 인출하여 내부 레지스터에 저장하고 명령어를 실행합니다.
이상적으로는, 모든 프로그램과 데이터에 메인 메모리에 영구히 존재하면 좋겠지만, 용량의 크기와 휘발성 메모리의 이유로 불가능합니다. 따라서 프로그램과 데이터를 저장하기 위한 저장장치로 보조저장장치를 사용합니다. 하드 디스크 드라이브(HDD)가 대표적인 예로, 메인 메모리와 비교하여 느리다는 단점이 존재하지만 비휘발성 메모리(NVM, non-volatile memory)이기 때문에 전원이 공급되지 않더라도 내용을 잃어버리지 않습니다.
일반적으로 CPU 가까이에 위치한 메모리 종류일수록 메모리가 작고 빠릅니다.
앞서 설명한 인터럽트 방식은 대량의 데이터를 이동하는데는 오버헤드를 유발할 수 있기 때문에 적합하지 않습니다. 이러한 문제를 해결하기 위해 직접 메모리 액세스(DMA, direct memory access) 방법을 사용합니다. 장치에 대한 버퍼 및 포인터, 입출력 카운트를 설정한 후 CPU의 개입 없이 직접 메모리로부터 데이터를 받거나 메모리로 데이터 블록 전체를 전송합니다. 한 바이트의 데이터 전송이 발생할 때 마다 인터럽트가 발생하는 것이 아니라, 하나의 데이터 블록이 전송될 때마다 인터럽트가 발생하는 것이 특징입니다. 이로 인해 데이터 블록을 전송하는 동안 CPU는 전송이 완료될 때까지 대기하지 않고 다른 작업을 처리하는 것이 가능합니다.
과거의 컴퓨터 시스템은 단일 처리 코어를 가진 하나의 CPU를 포함하는 단일 프로세서 시스템을 사용했습니다. 각 코어는 하나의 명령어를 실행하며, 데이터를 저장하기 위한 레지스터를 포함하고 있습니다. 이 때, 하나의 코어를 갖는 CPU가 하나만 있는 경우의 시스템을 단일 프로세서 시스템이라고 부릅니다.
현대의 컴퓨터 시스템이 사용중인 시스템으로, 두 개 이상의 프로세서를 포함하는 구조를 의미합니다. 프로세서는 컴퓨터 버스 및 메모리, 주변 장치를 공유합니다. 이에 따라 다중 프로세서 시스템은 처리량 증가라는 장점이 있습니다. 그러나 여러 프로세서가 동시에 작동하기 위해 발생하는 오버헤드와 공유 자원에 대한 경쟁으로 인해 프로세서가 늘어난다고 해서 성능이 정비례하여 증가하지는 않습니다.
일반적으로 다중 프로세서 시스템은 여러 개의 프로세서가 수행하는 방식에 따라 아래와 같이 분류할 수 있습니다.
각 프로세서가 메모리와 입출력 장치를 공유하며, 모든 프로세스가 동등하게 작동합니다.
각각의 프로세서는 독립적으로 실행되지만, 동일한 운영체제 이미지에서 작동합니다.
프로세서가 메모리와 입출력 장치를 공유하지 않으며, 각 프로세서가 특정 작업을 담당합니다.
일반적으로 하나의 프로세서는 운영체제와 관리 작업을 담당하며, 다른 프로세서들은 응용 프로그램의 실행을 담당합니다.
SMP 시스템과 AMP 시스템을 결합한 형태로, 각 프로세서가 메모리와 입출력 장치를 공유하는 부분과 공유하지 않는 부분이 있습니다.
클러스터 시스템은 다수의 독립적인 컴퓨터 시스템을 네트워크로 연결하여 하나의 시스템처럼 사용하는 시스템입니다. 네트워크로 연결된 이 시스템은 약하게 결합된(loosely coupled) 형태로, 각 컴퓨터는 공유 저장소에 액세스하며, 작업을 분담하여 처리합니다. 이를 통해 처리 속도와 시스템의 신뢰성 및 가용성을 높일 수 있습니다. 만약 한 노드에서 문제가 발생하면, 다른 노드가 문제가 발생한 노드의 소유권을 넘겨 받아 실행중이던 프로그램을 다시 시작할 수 있습니다. 그러나 이 시스템에서는 네트워크 대역폭, 데이터 일관성 등의 문제점이 존재합니다.
컴퓨터의 전원이 공급되면 보통 ROM 혹은 플래시 메모리에 저장된 부트스트랩 프로그램(bootstrap program)이 실행됩니다. 부트스트랩 프로그램은 CPU 레지스터에서 장치 컨트롤러, 메모리 내용에 이르기까지의 전반적인 시스템의 모든 측면을 초기화합니다. 부트스트랩 프로그램이 수행하는 주요 작업은 다음과 같습니다.
바이오스는 컴퓨터의 기본 입력 및 출력 시스템으로, 하드웨어의 초기화와 부팅 드라이버를 설정합니다.
부트스트랩 프로그램이 실행되면, 가장 먼저 바이오스가 초기화됩니다.
CPU 및 메모리, 입출력 장치 등의 하드웨어를 초기화합니다.
이 과정에서 메모리를 체크하여 오류가 발견되면 해당 메모리를 사용하지 않습니다.
운영체제가 설치된 위치를 찾아 부트 로더를 실행합니다.
부트 로더는 운영체제 커널 이미지를 로드하고 실행을 위한 준비 작업을 수행합니다.
부트 로더가 운영체제 커널 이미지를 로드하면, 운영체제는 초기화됩니다.
이 때 운영체제는 시스템 자원을 초기화하고 사용자 인터페이스를 시작합니다.
커널이 메모리에 적재되어 실행되면 시스템과 사용자에게 서비스를 제공할 수 있는 상태가 됩니다. 커널 외에도 커널이 실행되는 동안 백그라운드로 실행되는 시스템 데몬으로 일부 서비스도 같이 메모리에 적재됩니다.
다중 프로그래밍(Multiprogramming)과 다중 태스킹(Multitasking)은 컴퓨터 시스템의 성능을 향상시키기 위해 사용되는 방법입니다. 일반적으로 하나의 프로그램으로는 항상 CPU나 입출력 장치를 바쁘게 유지하기 어렵기 때문에 운영체제는 여러 프로그램을 실행시켜 시스템 자원이 유후상태에 있는 것을 방지하려 합니다.
다중 프로그래밍은 컴퓨터 시스템에서 여러 개의 동시에 실행되도록 하는 방법으로, 운영체제가 여러 프로세스를 동시에 메모리에 유지하고, 프로세스 중 하나를 선택하여 실행하기 시작합니다. 만약 해당 프로세스가 대기해야 하는 경우 CPU는 다른 프로세스로 전환하여 작업을 실행합니다.
다중 태스킹은 다중 프로그래밍 방법을 논리적으로 확장한 방법으로, 컴퓨터 시스템에서 여러 개의 작업(task)이 동시에 실행되도록 하는 방법입니다. 여러 개의 작업이 동시에 실행되며, 각 작업은 별도의 프로세스로 동작합니다. 각 프로세스는 자신이 필요로 하는 자원(CPU, 메모리, 입출력 장치 등)을 독점적으로 사용합니다.
이중 모드와 다중 모드(Dual-mode and Multi-mode)
운영체제와 사용자는 컴퓨터 시스템의 하드웨어 및 소프트웨어 자원을 공유하기 때문에 운영체제는 잘못된(혹은 악의적인) 프로그램으로 인해 다른 프로그램이나 운영체제 자체가 잘못 실행되는 경우가 없도록 보장해야 합니다. 이를 위해 운영체제는 운영체제에서 실행되는 코드와 사용자가 실행하는 코드를 구분할 수 있어야 합니다.
이를 위해 사용자 모드와 커널 모드로 분리하여 코드를 실행하는 방법을 이중 모드(dual mode)라고 합니다. 컴퓨터 하드웨어에는 사용자 모드와 커널 모드를 구분하기 위한 모드 비트(mode bit)가 존재하며, 이 비트가 0인 경우에 커널 모드, 1인 경우에 사용자 모드를 나타냅니다. 일반적으로 응용 프로그램이 실행될 때 사용자 모드에서 실행되며, 운영체제에서 제공하는 시스템 콜 등의 서비스를 사용하려 할 때 커널 모드로 전환 후 해당 서비스를 사용하게 됩니다.
컴퓨터 시스템이 시작할 때 하드웨어는 커널 모드에서 시작하며, 운영체제가 적재되고, 사용자 모드로 전환하여 사용자 프로세스가 시작됩니다. 사용자 프로세스가 실행되는 중에 트랩이나 인터럽트가 발생할 때마다 하드웨어는 사용자 모드에서 커널모드로 전환하여 처리합니다.
이렇게 운영체제의 영향을 끼칠 수 있는 명령어를 분리하고 커널 모드에서만 실행되도록 구분되어 있을 때 이와 같이 커널 모드에서만 실행 가능한 명령어를 특권 명령어(privileged instruction)이라고 합니다. 하드웨어는 특권 명령어가 커널 모드에서 실행되는지 확인하며, 사용자 모드에서 실행하려는 경우 하드웨어는 이를 실행하지 않고 비정상적인 명령어로 간주하여 운영체제로 트랩을 겁니다. 커널 모드로 전환하는 명령어가 특권 명령어의 대표적인 예로, 이 외에도 입출력 제어, 타이머 관리 및 인터럽트 관리 등이 있습니다.
다중 모드는 이중 모드에서 확장된 개념으로 보안성과 안정성을 높이기 위해서 사용되는 방법으로, 커널 모드와 사용자 모드 외에 추가적인 모드를 제공하는 방법입니다. 예를 들어 가상화에서는 가상화 모드(hypervisor mode)라는 모드가 추가적으로 제공되며, 이 모드에서는 하이퍼바이저(hypervisor)가 실행되어 다수의 가상 머신을 관리합니다.
사용자 프로그램이 커널 모드에서 실행되어 운영체제의 서비스를 사용하기 위해서는 시스템 콜(system call)을 호출해야 합니다. 시스템 콜은 일반적으로 인터럽트 벡터의 특정 위치로 트랩을 거는 형태로 구성되어 있으며 보통 trap 명령어 혹은 syscall 명령어에 의해 트랩이 발생됩니다.
시스템 콜은 하드웨어에 의해 하나의 소프트웨어 인터럽트로 취급되며, 전반적인 제어가 인터럽트 벡터를 통해 운영체제 내의 서비스 루틴으로 전달되고, 모드 비트가 커널 모드로 설정됩니다. 커널은 인터럽트를 발생시킨 명령어를 검사하여 어떤 시스템 콜이 발생했는지를 검사하고, 시스템 콜을 처리한 뒤 다시 원래의 명령어로 복귀합니다.
운영체제에서 타이머(timer)는 프로세스 스케줄링과 관련된 작업을 수행하는데 사용되는 도구입니다. 사용자 프로그램이 무한 루프(infinite loop)에 빠지거나 시스템 서비스 호출에 실패하여 운영체제로 복귀하지 못하는 경우가 없도록 반드시 방지해야 합니다. 이를 위해 운영체제에서는 타이머를 사용하여 지정된 시간 이후에 인터럽트가 발생하도록 설정하여 방지할 수 있습니다.
운영체제에서 타이머는 하드웨어의 타이머를 사용하여 구현되었습니다. 일반적으로 고정률의 클록(fixed-rate clock)과 계수기를 사용하여 구현되었으며, 운영체제가 계수기 값을 설정하고, 하나의 클록 신호가 발생할 때 마다 계수기 값이 하나씩 감소하여, 계수기 값이 0이 되었을 때 인터럽트가 발생한다.
운영체제는 앞서 말한 역할 외에도 자원 관리의 역할을 수행합니다. 여기서 말하는 자원이란, 시스템의 CPU, 메모리 공간 및 저장 공간, 입출력 장치 등을 의미합니다.
프로그램은 디스크에 저장된 실행 가능한 파일를 의미하며, 프로세스는 실행 중인 프로그램을 의미합니다. 프로세스는 작업을 수행하기 위해 CPU 시간, 메모리, 파일 및 입출력 장치 등을 포함한 여러 가지 자원을 필요로 합니다. 이러한 자원은 프로세스가 실행되는 동안(런타임, runtime) 할당됩니다. 프로세스는 다음에 수행할 명령어를 지정하는 프로그램 카운터(PC, Program Counter)를 포함하는 능동적인 개체로, 명령어는 순차적으로 실행되며, 한 프로세스의 명령어는 반드시 하나씩 실행됩니다.
이러한 프로세스를 위해 운영체제는 효율적인 프로세스 관리를 위해 아래 활동을 책임지는 역할을 갖습니다.
사용자 프로세스와 시스템 프로세스의 생성과 제거
프로세스와 쓰레드를 CPU에 할당하기 위한 스케줄링
프로세스의 일시 중지와 재실행
프로세스 동기화를 위한 기법 제공
프로세스 통신을 위한 기법 제공
컴퓨터 시스템에서는 메인 메모리는 앞서 설명한 것처럼 시스템이 작동하는데 중추적인 역할을 수행합니다. CPU가 명령어 인출 사이클(instruction fetch-cycle) 동안 메인 메모리로부터 명령어를 읽고, 자료 인출 사이클(data fetch-cycle) 동안 메인 메모리로부터 필요한 데이터를 읽거나 쓰는 작업을 하는데 사용하는 등 CPU가 직접 접근할 수 있는 유일한 메모리로써 그만큼 중요한 역할을 담당하고 있습니다.
CPU의 이용률과 컴퓨터의 응답 속도를 개선하기 위해서 메모리에는 여러 개의 프로그램을 유지해야 하며 이를 위해서는 효율적인 메모리 관리 기법이 필요합니다. 대표적인 기법으로는 다음과 같은 예가 있습니다.
단일 분할 할당(single partition allocation)
다중 분할 할당(multiple partition allocation)
페이지(page)
세그먼트(segmentation)
이러한 메모리 관리 기법 중 어떤 기법이 적절한가는 여러 요인에 의해 결정됩니다. 특히 하드웨어 설계에 따라 선택되는 메모리 관리 기법이 달라집니다.
위에서 설명한 것과 같이 효율적으로 메모리를 관리하기 위해서 운영체제는 다음과 같은 역할을 갖습니다.
메모리의 어느 부분이 사용되고 있으며, 어느 프로세스에 의해 사용되고 있는지 추적합니다.
필요에 따라 메모리 공간을 할당하고 회수합니다.
어떤 프로세스들을 메모리에 적재하고 제거할 지 결정합니다.
파일 시스템 관리(file system management)는 운영체제에서 수행하는 또 다른 중요한 역할입니다. 저장장치의 물리적인 특징을 추상화하여 논리적인 저장 단위인 파일로 데이터를 관리합니다. 운영체제는 파일을 물리적 매체로 매핑하여 저장장치를 통해 파일에 접근할 수 있습니다.
운영체제는 파일 시스템 관리를 위해 다음과 같은 역할을 수행합니다.
파일 및 디렉토리 생성, 삭제, 이동, 복사 등의 작업을 수행합니다.
파일 및 디렉토리의 보안을 관리하고, 접근 권한을 설정합니다.
파일 및 디렉토리의 백업 및 복구 기능을 제공합니다.
파일 시스템은 다양한 종류가 있으며, 운영체제가 제공하는 파일 시스템 외에도 다양한 파일 시스템이 존재합니다. 대표적인 파일 시스템으로는 FAT, NTFS, ext, HFS 등이 있습니다.
캐싱(caching)은 컴퓨터 시스템에서 중요한 원리입니다. 데이터는 메인 메모리와 같은 저장장치에 저장되는데, 자주 사용되는 데이터는 더 적은 용량을 갖지만 더 빠른 읽기 및 쓰기 속도를 갖는 캐시에 일시적으로 복사하여 사용합니다. CPU 내부의 레지스터들 또한 메인 메모리를 위한 캐시로 볼 수 있습니다.
캐시는 앞서 말한 것처럼 크기가 제한되어 있으므로 캐시 관리는 중요한 문제입니다. 캐시의 크기와 교체 알고리즘을 적절하게 선택하면 캐시의 성능을 크게 향상시킬 수 있습니다.
캐시와 메모리는 계층적인 구조 형태를 갖고 있습니다. CPU에 가장 가까운 레지스터부터 L1 캐시 및 L2 캐시, 그리고 메인 메모리와 보조 저장 장치 순으로 계층적인 구조를 가집니다. 오직 하나의 프로세스만을 사용하는 컴퓨터 시스템에서는 이러한 계층적인 구조가 문제가 되지 않지만, 여러 개의 프로세스가 실행되는 상황에서는 이야기가 달라집니다. 예를 들어, 여러 개의 프로세스가 데이터 A를 필요로 하는 상황에서 첫 번째 프로세스가 특정 계층에 있는 데이터 A를 갱신했다고 했을 때, 다른 프로세스가 다른 계층에 있는 데이터 A를 가져왔을 때 갱신된 데이터 A를 가져올 수 있어야 합니다. 즉, 특정 데이터가 갱신되는 경우 해당 데이터가 존재하는 모든 캐시에 즉각적으로 반영될 수 있어야 합니다. 이러한 문제를 캐시 일관성 문제라고 합니다.
운영체제는 입출력 장치와의 상호작용을 조율하고, 입출력 작업이 원할하게 수행하도록 입출력 시스템을 관리합니다. 일반적으로 입출력 시스템은 다음과 같이 구성되어 있습니다.
버퍼링, 캐싱, 스풀링 등을 포함한 메모리 관리 요소
일반적인 장치 드라이버 인터페이스
특정 하드웨어 장치들을 위한 드라이버
입출력 시스템 관리의 핵심은 입출력 장치의 다양한 특성과 작동 방식을 규격화하여 시스템과 상호작용할 수 있는 방식을 효율적으로 제공하는 것입니다.
컴퓨터 시스템은 다수의 사용자를 가지며 다수의 프로세스 작업을 병행으로 수행하기 때문에 데이터에 대한 접근은 반드시 규제되어야 합니다. 이를 위해 운영체제로부터 허가를 획득한 프로세스만이 작업할 수 있도록 보장하는 방법이 필요합니다.
이를 위해 운영체제에서는 시스템 내부에서 자원에 대한 접근을 제어하여 안전하게 보호(protection)하고 있습니다. 프로세스 간 혹은 사용자 간에 자원 공유가 발생하면, 다른 프로세스가 사용자가 자원에 대한 무단 접근을 시도할 수 있으므로, 이를 방지하기 위해 컴퓨터 시스템은 보호 메커니즘을 사용하여 각 프로세스 혹은 사용자에게 필요한 자원만 제공합니다.
컴퓨터 시스템이 충분한 보호 기능을 가지고 있더라도 여전히 부적절한 접근이 발생할 수 있습니다. 예를 들어, 사용자의 인증 정보가 도난당했다고 가정하면, 파일과 메모리 보호 기능이 아무리 잘 작동하더라도 사용자의 데이터는 복사 혹은 삭제될 수 있습니다. 이러한 외부 혹은 내부의 공격을 방어하는 것이 보안(security) 기능입니다. 시스템의 많은 범위에 대해 공격이 가능한 바이러스, 웜, 서비스 거부 공격 등으로부터 컴퓨터 시스템은 보호합니다. 일반적으로 사용자 인증, 권한 관리, 암호화, 방화벽 등 다양한 기술이 사용됩니다.