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