운영체제란 무엇인가?
운영체제는 컴퓨터 프로그램이 하드웨어 자원을 이용할 수 있도록 하는 특수 소프트웨어 계층이다. 이는 컴퓨터 하드웨어와 사용자 응용 프로그램 사이에서 중개자 역할을 하며, 소프트웨어가 하드웨어와 일관되고 효율적으로 상호 작용할 수 있도록 한다. 운영 체제는 메모리 관리, 입력 및 출력 장치 처리와 같은 물리적인 인터페이스와 이를 추상화한 소프트웨어적인 인터페이스를 제공한다. 인기있는 운영 체제의 예로는 Windows, macOS, Linux 및 Android가 있다.
컴퓨터 게임을 하는 상황을 가정해보자. 키보드와 마우스를 통해 게임 캐릭터를 움직여주고 화면을 통해 출력되는 게임 화면을 본다. 내부적으로는 메모리에 게임 데이터가 적재된다. 게임을 플레이하다 저장 버튼을 누르면 디스크에 현재까지 게임이 플레이된 내용이 저장된다. 이와 같은 과정들은 어떻게 구현되는 것일까?
운영체제는 키보드, 마우스, 모니터, 메모리, 파일 등등과 같은 하드웨어 자원들을 이용할 수 있도록 추상화된 인터페이스를 제공한다. 키보드 인풋이 감지되면 키보드 디바이스 드라이버를 통해 입력된 데이터를 어플리케이션 레벨까지 전달시킬 수 있도록 한다. 게임에서 메모리를 요구하는 상황이 오면 가상 메모리를 거쳐 실제 메모리의 공간을 할당해준다. 화면에 게임을 렌더링해야하는 상황이 오면 출력시킬 데이터를 그래픽 드라이버를 통해 모니터로 뿌려준다. 운영체제는 이처럼 다양한 하드웨어 자원들을 관리하며 필요하다면 어플리케이션에서 시스템 함수들을 사용하여 운영체제를 통해 하드웨어 자원을 이용할 수 있도록 돕기도 한다.
운영체제가 하드웨어 자원을 추상화된 인터페이스로 제공함으로써 갖는 장점들은 어떤 것들이 있을까?
프로그램이 특정 하드웨어에 종속되지 않도록 한다.
운영체제라는 추상화 레이어가 없다면, 개발자가 작성한 코드는 그 코드를 돌리기 위한 하드웨어에 종속된다. 즉, 이 소프트웨어는 해당 하드웨어에서만 동작하고, 다른 하드웨어에서는 동작하지 않을 것이다.
(RAM을 갈아끼면 동작하지 못하고, 모니터를 바꾸면 동작하지 않는 게임을 상상해보자.)
하드웨어 자원 관리에 대한 개발에 대해 신경쓰지 않아도 된다.
운영체제는 하드웨어 자원 관리에 대한 수 많은 작업들을 담당하고 있다. 이 과정은 어플리케이션 레벨 아래에서 일어나며, 일반적으로는 개발자가 크게 신경쓰지 않아도 알아서 관리된다.
(new Object() 할 때마다 RAM의 현재 메모리 적재 상태를 확인해가며 메모리를 할당해야한다면 어떨까?)
보안과 안정성을 관리하는 시스템을 제공한다.
운영체제는 하드웨어 접근을 제어하고 관리함으로써, 애플리케이션들이 시스템 자원을 안전하고 효율적으로 사용할 수 있도록 한다. 또한, 잘못된 하드웨어 접근으로부터 시스템을 보호할 수 있다.
자원 관리의 최적화
운영체제는 메모리, CPU 시간, 디스크 공간 등의 자원을 효율적으로 관리하고 할당한다. 이는 시스템의 전반적인 성능을 향상시키고, 자원 충돌과 낭비를 최소화한다.
하드웨어 이용을 위한 사용자 인터페이스 제공
운영체제는 사용자와 하드웨어 사이의 상호 작용을 위한 인터페이스를 제공한다. 이는 사용자가 시스템을 보다 쉽게 조작할 수 있게 하며, 그래픽 사용자 인터페이스(GUI)는 이를 더욱 직관적으로 만든다.
이처럼 운영체제는 마법사(Illusionist)와 같은 역할을 한다. 운영체제는 어렵고 복잡한 하드웨어에 대한 깔끔하고 쉬운 추상화를 제공하며, 사용자들로 하여금 무한한 메모리를 제공할 수 있는 것처럼 동작한다. 또한 파일과 같은 인터페이스를 제공하여 실제 데이터가 어떤 형태의 디스크에 저장되는지와 같이 특수적인 상황에 대해 걱정할 필요가 없도록 한다.
운영체제의 기능
운영체제는 하드웨어의 자원들을 추상화한 인터페이스로 제공하는 특수한 소프트웨어라 정의하였었다. 그렇다면 운영체제가 어떤 하드웨어들을 어떤 개념들로 추상화하는지 알아보자.
운영체제는 하드웨어 프로세서(CPU)를 스레드(Thread)의 개념으로 추상화하여 제공한다. 스레드는 명령어 집합(ISA)에 정의된 명령어대로 코드를 실행하는 실행의 한 단위이다. 실행이라는 과정을 위해 프로세서로부터 계산을 위한 자원을 공급받는다. 사용자들은 스레드라는 인터페이스를 통해서 하드웨어 프로세서의 자원들을 활용할 수 있다.
하드웨어 메모리(RAM ..)를 주소 공간(Address Spaces)의 개념으로 추상화하여 제공한다. 주소 공간은 메모리에 접근할 수 있는 인터페이스로, 사용자들은 이 공간을 활용하여 하드웨어 메모리에 데이터를 할당 및 해제할 수 있다.
하드웨어 저장공간(Disk ..)를 파일(File)의 개념으로 추상화하여 제공한다. 사용자는 USB에 데이터를 저장하든, 디스크에 데이터를 저장하든 신경쓸 필요 없이 파일이라는 통일된 인터페이스를 통해 다양한 스토리지들에 데이터를 저장할 수 있다.
하드웨어 네트워크 카드를 소켓(Socket)의 개념으로 추상화하여 제공한다. 사용자는 네트워크 카드를 통해 외부 컴퓨터와 통신해야하는 상황을 소켓 인터페이스를 활용하여 해결할 수 있다.
또한 그 외 다양한 하드웨어 자원들을 여러 종류의 디바이스 드라이버 (Device Driver)로 추상화하여 제공한다. 사용자는 키보드, 마우스, 사운드와 같은 I/O 장치들을 디바이스 드라이버라는 인터페이스를 통해 사용할 수 있다.
운영체제는 이와 같은 다양한 기능들을 활용하는 프로그램 인스턴스를 프로세스(Process)의 개념으로 추상화하여 제공한다. 프로세스는 운영체제의 각종 자원들을 활용하는 하나의 독립된 단위로, 사용자들로 하여금 각종 자원들을 효과적으로 활용할 수 있도록 한다.
사용자는 시스템 라이브러리를 이용하여 운영체제의 자원을 활용하는 프로그램을 작성할 수 있다. 이렇게 작성된 프로그램은 운영체제에서 프로세스라는 단위로 인스턴싱되어 관리되고, 사용자가 작성한 일련의 동작을 수행한다.
운영체제는 여러 개의 프로세스들을 관리한다. 각 프로세스들은 서로 독립된 메모리 공간을 이용하며 사용되는 공간들은 운영체제에 의해 보호된다. 서로가 서로의 메모리에 접근하거나, 특정 프로세스가 잡고있는 파일에 접근하는 상황들이 보호되기 때문에, 수 많은 프로그램들이 동시에 동작하더라도 서로 영역을 침범함으로써 생기는 문제들에 대해 안전하다.
또한 운영체제는 여러 개의 프로세스들이 동시에 동작하도록 한다. 운영체제는 어떻게 이것을 가능하게 할 수 있을까?
하나의 CPU에 하나의 프로세서만 있다고 가정해보자.
먼저 운영체제는 프로세서로 Process1의 컴파일된 코드를 실행시킨다. 이때 프로세서를 통해 참조되는 메모리도 Process1의 메모리이다. Process1을 잠깐동안 실행시킨 후, 프로세서는 Process2를 실행시킨다. 참조되는 메모리도 Process2의 메모리로 바뀐다. 또 잠깐 동안 실행시킨 후, 다시 Process1로 되돌아가고 이 과정을 반복한다. CPU 프로세서의 처리속도는 엄청나게 빠르기 때문에, 지금 과정을 빠르게 수행한다면 여러 개의 프로세스들이 동시에 동작하는것처럼 보이게 된다. 운영체제는 이와 같은 방법으로 하나의 프로세서만 갖고도 프로세스들을 동시에 동작시킬 수 있다.