운영 체제란?
카테고리: OSMarch 10, 2021
운영 체제란 무엇인가
운영 체제 (Operating System)란, 쉽게 말해 컴퓨터의 하드웨어를 관리하는 소프트웨어라고 할 수 있습니다. 즉, 우리가 일상 생활에서 많이 사용하는 브라우저, 엑셀, 워드 같은 애플리케이션 프로그램들이 컴퓨터 하드웨어 위에서 원활히 동작할 수 있도록 일종의 중간 계층 역할을 하는 프로그램이라고 할 수 있습니다. 데스크톱, 노트북뿐만 아니라 스마트폰, 심지어 자동차, IoT 기기를 포함하는 모든 가전제품에도 OS가 존재합니다.
운영 체제의 역할을 좀 더 살펴보려면 우선 CPU, 메모리, 입/출력장치 등과 같은 컴퓨터 하드웨어에 대한 이해가 필요한데, 그림 1-1에 컴퓨터의 주요 부품들에 대한 큰 그림이 나와 있습니다. 여기서, 하드웨어는 맨 밑에 자리하고 있는데, 앞서 말한 CPU, 메모리, 디스크 및 키보드, 모니터 등과 같은 입/출력장치가 여기에 속합니다. 하드웨어 위에는 소프트웨어가 위치하고 있습니다.
대부분의 컴퓨터에는 두 개의 동작 모드가 존재하는데, 하나는 커널(kernel)모드 이고, 다른 하나는 유저 모드 입니다. 커널 모드에서는 모든 하드웨어에 대해 완전한 접근을 할 수 있고, 또 컴퓨터가 수행할 수 있는 모든 종류의 명령을 수행할 수 있습니다. 운영 체제는 바로 이 커널 모드로 동작합니다. 그 외 나머지 소프트웨어들은 유저 모드에서 동작하는데, 유저 모드에서는 일부분의 명령만을 수행할 수 있습니다. 특히, 유저모드에서는 하드웨어를 조작하거나 I/O에 관한 동작을 수행할 수 없습니다.
또, shell 혹은 GUI라고 불리는 유저 인터페이스 프로그램은 소프트웨어 레벨 중에서 맨 아랫단에 위치합니다. 이 프로그램들은 사용자로 하여금 웹 브라우저, 워드 프로세서 등과 같은 다른 프로그램을 실행할 수 있도록 도와줍니다. 유저 인터페이스 프로그램들 또한 운영 체제를 많이 사용합니다.
종합해 보면, 위 그림에서 보듯이 운영 체제는 모든 소프트웨어에 대한 기초를 제공해 줌으로써 유저 프로그램들이 잘 동작하게끔 해줍니다.
📌 운영 체제를 공부해야 하는 이유? |
---|
실제로 운영 체제를 개발하는 사람은 극소수일 텐데, 왜 우리가 직접 개발할 것도 아니고 유지보수할 것도 아니면서 운영 체제를 배워야 하는 걸까요? 정말 단순하게 생각해보면, 대부분의 프로그램이 운영 체제 위에서 동작하기 때문입니다. 이 때문에 적어도 운영 체제의 동작 원리 정도는 알아야 더 효율적이고 효과적인 프로그램을 개발할 수 있을 것입니다. 따라서 운영 체제의 기초 및 운영 체제가 하드웨어를 제어하는 방법, 그리고 운영 체제가 어떠한 기능들을 사용자(개발자)에게 제공하는지를 아는 것은 운영 체제를 직접 개발하고 유지보수하는 사람들뿐만 아니라 일반적인 애플리케이션을 만드는 개발자에게도 중요하다고 할 수 있습니다. |
컴퓨터 시스템 구성
현대 컴퓨터들은 대부분 하나 이상의 CPU(혹은 코어)들과 버스(bus)로 연결된 여러 개의 장치 컨트롤러(device controller)들로 구성되어 있고, 각 장치 컨트롤러들은 이름 그대로 장치들(예를 들어 디스크 드라이브, 오디오/비디오 장치, 입/출력 장치)을 관리합니다. USB와 같이, 장치 컨트롤러에 따라 하나의 컨트롤러에 하나 이상의 하드웨어가 연결될 수도 있습니다. 장치 컨트롤러는 일종의 “칩”으로서 물리적으로 장치들을 관리합니다. 내부에 자체적으로 버퍼를 두고, 특별한 역할을 하는 레지스터를 두고 있으며, 데이터들을 버퍼에서 꺼내 다른 주변 장치들과 주고받는 역할을 합니다. 대부분 이러한 장치들을 제어 하는 것이 매우 복잡하므로, 장치 컨트롤러는 운영 체제에게 좀 더 간편화된(그럼에도 복잡하지만..!) 인터페이스를 제공합니다.
운영 체제는 이러한 장치 컨트롤러들에게 명령을 내리고 그 결과를 받아서 처리하는 장치 드라이버(device driver)라는 것을 가지고 있습니다. 장치 드라이버를 사용하기 위해선 장치 드라이버들이 운영 체제 내부에 위치하여 커널 모드로 동작해야 합니다. 현대의 운영 체제(리눅스, 윈도우 등)들은 드라이버들이 커널 밖에서도 동작할 수 있도록 하지만, 여전히 대부분의 드라이버들은 커널 영역 안에서 작동합니다.
아래 그림 1-2는 일반적인 컴퓨터 시스템의 구조를 나타내고 있습니다:
자원 관리자로서의 운영 체제
앞서 살펴본 것처럼, 프로그램에게 하드웨어의 추상화를 제공하는 관점은 top-down 관점입니다. 반대로, bottom-up 관점에서 보자면 운영 체제는 복잡한 시스템의 모든 부분을 관리한다고 볼 수 있습니다. 현대 컴퓨터들은 CPU, 메모리, 디스크, I/O 장치, 그 외 여러 다양한 장치들로 구성되어 있다고 했는데, 이러한 장치들을 사용하고자 하는 여러 프로그램들에게 하드웨어 자원들을 정돈되고 세심한 방식으로 제공하는 것이 운영 체제의 역할입니다.
현대 운영 체제들은 여러 프로그램이 메모리에 상주하여 동시에 돌아가도록 합니다. 이때 만약 세 개의 프로그램이 각자 자신들의 결과를 프린터에 출력하고자 한다고 해봅시다. 원래라면 1, 2, 3번 프로그램의 결과물이 차례로 출력되어야 하지만, 이들의 순서가 뒤죽박죽되어 출력될 수도 있습니다. 따라서 운영 체제가 어떤 하나의 프로그램이 종료되면 그 결과물이 곧장 프린터로 향하도록 하는 것이 아니라, 해당 결과물을 복사하는 동시에, 다른 프로그램이 계속해서 출력을 만들도록 할 수 있습니다.
또한, 컴퓨터 (혹은 네트워크)의 사용자가 두 명 이상이라면, 사용자끼리 서로 간섭할 수도 있을 것입니다. 게다가, 하드웨어뿐만 아니라 데이터도 공유해야 하는 상황이 발생할 수 있는데, 이때 운영 체제는 어떤 프로그램(혹은 사용자)이 어떤 자원을 사용하고 있는지 추적하고 자원 접근에 대한 요청을 관리함으로써 서로 다른 유저들의 요청들이 충돌하는 것을 방지하는 역할을 합니다.
자원 관리는 두 개의 멀티플렉싱 방식을 이용합니다. 하나는 시간에 관한 멀티플렉싱 이고, 다른 하나는 공간에 관한 멀티플렉싱 입니다.
한 자원이 시간에 대해 멀티플렉싱(time multiplexed) 된다는 것은, 서로 다른 프로그램(혹은 사용자)이 돌아가면서 자원을 사용한다는 것을 말합니다. 이들 중 첫 번째가 먼저 자원을 사용하고, 그 다음 두 번째가 자원을 사용하고, 또 세 번째가 사용하고, … 를 반복합니다. 예를 들어, 하나의 프로세서에 대해 여러 개의 프로그램이 CPU 자원을 사용하고자 할 때, 운영 체제는 우선 하나의 프로그램에게 자원을 할당하고, 해당 프로그램이 어느 정도 실행되면 다른 프로그램에게 자원을 할당합니다. 이 자원을 어떻게 시간에 대해 멀티플렉싱 할 것인지, 즉 어떤 프로그램이 얼마나 자원을 사용할 것인가에 대해서 결정하는 것은 운영 체제의 몫입니다.
한 자원이 공간에 대해 멀티플렉싱(space multiplexed) 된다는 것은, 시간에 대해 멀티플렉싱 하는 경우처럼 서로 돌아가면서 자원을 사용하는 것이 아니라, 각각의 프로그램들이 자원의 일부분을 나눠 사용하는 것을 말합니다. 예를 들어, 메인 메모리를 여러 부분으로 나눠 각 프로그램에 할당함으로써 여러 프로그램이 메모리에 동시에 상주하도록 할 수 있습니다. 만약 메모리에 충분한 공간이 있다고 하면, 이 공간들을 적절히 나누어 여러 프로그램을 동시에 상주하도록 하는 것이 한 프로그램에게 몰아주는 것보다 훨씬 효율적일 것입니다. 물론, 자원 배분의 공정성, 보안과 같은 문제들이 발생할 수 있는데 이것 또한 운영 체제가 관리해야 하는 부분입니다.
운영 체제의 핵심 개념들
대부분의 운영 체제들은 프로세스, 주소 공간(address space), 파일과 같은 기본적인(그리고 추상적인) 개념들을 제공합니다. 여기선 이러한 주요 개념들을 간략하게 살펴봅시다.
프로세스(Processes)
프로세스는 쉽게 말해 현재 메인 메모리에 로드되어 실행 중인 프로그램, 혹은 어떤 프로그램을 실행하는데 필요한 정보들이 담긴 컨테이너라고 할 수 있습니다. 각 프로세스에는 프로세스가 읽고 쓸 수 있는 메모리 공간인 주소 공간이 존재합니다.
여러 개의 프로그램이 돌아가는 멀티프로그래밍 시스템을 생각해봅시다. 사용자는 비디오 편집 프로그램을 통해 1시간짜리 동영상을 특정 포맷으로 변환하는 동시에 웹 브라우저로 웹 서핑을 할 수 있습니다. 동시에 백그라운드에서는 새로운 이메일 수신 여부를 체크하는 프로그램이 돌아가고 있을 수도 있습니다. 이 예시에서는 적어도 세 개의 프로세스가 동작하고 있는데, 운영 체제는 이러한 프로세스들 중에 현재 어떤 프로세스를 실행시킬 것인가를 결정합니다.
만약 어떤 한 프로세스의 실행이 잠시 중단되면, 이후에 중단된 시점에서 다시 실행하기 위해 프로세스의 현재 상태를 어딘가에 저장해야만 합니다. 대부분의 운영 체제들은 이러한 프로세스의 상태를 (프로세스의 주소 공간은 제외) 프로세스 테이블(process table)이라는 곳에 저장합니다.
주소 공간 (Address Spaces)
현대 운영 체제에서는 여러 프로세스들이 동시에 메인 메모리에 로드되는데, 이때 각각의 프로세스들이 서로를 간섭하는 것을 막기 위해 일종의 보호 메커니즘이 필요합니다. 이러한 메커니즘은 하드웨어로 구현되어 있지만 운영 체제에 의해 제어됩니다.
메모리와 관련된 또 다른 주요 사안은 바로 프로세스의 주소 공간을 관리하는 것입니다. 주소 공간의 크기는 CPU의 주소 버스(address bus)의 크기에 따라 결정되는데, 만약 주소 버스가 32비트인 시스템에서는 0부터 232 - 1 까지의 주소 범위를 제공할 수 있습니다.
하지만 만약 프로세스가 메인 메모리보다 더 큰 공간을 사용하고자 하면 어떻게 될까요? 초창기의 컴퓨터 시스템에서는 이러한 것이 허용되지 않았습니다만, 현대의 컴퓨터 시스템들은 가상 메모리(virtual memory)라는 기술을 통해 메인 메모리보다 더 큰 주소 공간에 대해 주소 공간 일부분은 메인 메모리에 두고, 나머지 부분은 디스크에 두어 말 그대로 가상의 메인 메모리 역할을 하게끔 할 수 있습니다.
주소 공간은 컴퓨터의 실제 물리적인 메모리와는 분리해서 생각해야 합니다. 즉, 주소 공간은 물리적인 메모리보다 더 클 수도 있고 작을 수도 있습니다. 주소 공간과 물리적인 메모리 관리는 운영 체제의 핵심 기능 중 하나입니다. 어떻게 보면 주소 공간은 물리적인 메인 메모리를 추상화한 개념이라고 할 수도 있을 것 같습니다.
파일 (Files)
또 다른 주요 컨셉은 파일 시스템입니다. 앞서 살펴봤듯이, 운영 체제의 주요 기능 중 하나는 바로 디스크와 I/O 장치의 복잡한 구조를 추상화하여 프로그래머가 해당 장치들을 손쉽게 쓸 수 있게 하는 것입니다.
파일들을 저장하는 공간을 제공하기 위해, 운영 체제는 일종의 “그룹” 개념인 디렉토리(directory, or folder)라는것을 제공합니다. 다음 그림은 이러한 파일 시스템의 계층적 모델을 보여주고 있습니다:
파일을 읽거나 쓰기 전에 무조건 해당 파일을 열어야(open) 하며, 이때 필요한 경우 사용자의 접근 권한을 체크합니다. 만약 해당 파일에 접근할 수 있는 권한이 있다면 시스템은 파일 서술자(file descriptor)라고 하는, 이후의 동작에서 사용될 정수를 반환합니다. 만약 해당 파일에 접근할 수 없다면 에러 코드가 반환됩니다.
여기서 마지막으로 살펴볼 것은 프로세스 및 파일과 관련된 파이프(pipe)라고 하는 개념입니다. 파이프는 일종의 가짜(pseudo) 파일로서, 아래 그림과 같이 두 개의 프로세스를 연결하는 역할을 합니다:
만약 두 프로세스 A와 B가 파이프를 통해 서로 통신하고자 한다면, 반드시 사전에 파이프를 연결해야 합니다. 파이프는 실제로 파일과 매우 흡사하게 구현되어 있는데, 프로세스 A가 B에 데이터를 전송하고자 할 때 프로세스 A는 파이프를 마치 출력 파일인 것처럼 취급하여 데이터를 파이프에 기록합니다. 그러면 프로세스 B는 파이프에 기록된 데이터를 마치 입력 파일인 것처럼 취급하여 데이터를 읽습니다. 이처럼 파이프를 이용한 프로세스 간의 통신은 일반적인 파일 읽기·쓰기 방식과 매우 흡사합니다.
I/O
모든 컴퓨터는 데이터를 읽고, 결과물을 출력하는 물리적인 장치를 가지고 있습니다. 만약 이러한 장치들이 없다면, 즉 컴퓨터가 사용자로부터 데이터를 입력받지 못할뿐더러 연산의 결과물을 출력하지 못한다면 컴퓨터를 사용할 이유가 없을 테죠. I/O 장치에는 키보드, 모니터, 마우스, 프린터 등과 같은 것들이 존재합니다. 이러한 장치들을 관리하는 것이 운영 체제의 역할입니다.