본문 바로가기
컴퓨터공학/기초

운영 체제 OS

by 하이방가루 2022. 8. 25.
728x90
반응형

이 글은 Crash Course의 Computer Science를 보고 정리한 글입니다.

  1940년대와 50년대 초반의 컴퓨터는 한 번에 한 개의 프로그램을 실행했다. 프로그래머는 자신의 책상에서 프로그램을 펀치카드에 하나를 쓰듯이 썼다. 그런 다음, 그것을 방 크기의 컴퓨터가 있는 방으로 가져와서 전용 컴퓨터 운영자에게 건넸다. 운영자는 프로그램을 컴퓨터에 공급한다. 컴퓨터는 그것을 실행하고 출력을 내뱉고 정지한다.

  이 수동적인 프로세스는 컴퓨터가 중간에 느려졌을 때, 다시 처음으로 돌아가서 프로그램을 실행하는 데에는 종종 몇 시간, 며칠 또는 몇 주가 걸렸다. 그러나 컴퓨터는 계속해서 빨라졌고, 인간이 뛰어다니면서 판독기들에게 프로그램을 삽입하는 것은 실제 프로그램 자체를 실행하는 것보다 오래 걸리게 됐다. 따라서 컴퓨터가 스스로 작동할 수 있는 방법이 필요해졌다. 그리하여 운영 체제(Operating Systems; OS)가 탄생하게 되었다.

 

  OS는 프로그램과 같다. 그러나 하드웨어에 대한 특별한 권한을 갖고, 다른 프로그램을 실행하고 관리할 수 있다. OS는 일반적으로 컴퓨터 전원을 처음 켰을 때 시작하는 프로그램이며 모든 후속 프로그램은 OS에 의해 시작된다. OS는 컴퓨터가 더욱 광범위하고 강력해진 1950년대에 시작되었다. 최초의 OS는 수작업으로 프로그램을 로드하는 일상적인 수동 작업을 보강했다. 한 번에 하나의 프로그램을 받는 대신, 컴퓨터가 일괄적으로 배치할 수 있었다. 컴퓨터가 하나를 완료하면 자동으로 거의 즉시 다음 프로그램을 시작한다. 누군가가 사무실에서 다음 프로그램을 찾느라 고생하는 동안 가동 중단되는 시간이 없어진 것이다. 이를 일괄 처리(Batch Processing)라고 한다.

 

  컴퓨터가 더 빨라지는 동안, 가격은 내려갔다. 그래서 전 세계 곳곳에서, 특히 대학과 관공서에서 사용되었다. 곧 사람들은 소프트웨어를 공유하기 시작했다. 그러나 문제가 있었다. Havard Mark 1이나 ENIAC과 같은 유일성 컴퓨터 시대에는 프로그래머들만이 하나의 기계에 대한 코드를 써야만 했다. 프로세서, 펀치 카드 판독기 및 프린터는 이미 알려져 있었고 변함이 없었다. 그러나 컴퓨터가 널리 보급되면서, 컴퓨터 구성이 항상 동일하지는 않았다. 마치 컴퓨터들의 CPU는 같지만 프린터는 같지 않은 것처럼 말이다. 이는 프로그래머에게 커다란 고통이었다. 프로그래머들은 프로그램 작성에 대해 걱정할 뿐만 아니라 모든 모델의 프린터를 포함한 컴퓨터에 연결된 주변 장치들과의 접속하는 방법 또한 걱정해야 했다. 

  초기 주변장치와의 접속은 낮은 수준이어서 프로그래머는 각 장치에 대한 하드웨어 세부 정보를 알아야 했다. 게다가 프로그래머가 주변 장치의 모든 모델에 접근하여 코드를 테스트하는 경우는 거의 없었다. 그래서 프로그래머들은 종종 설명서만 읽으면 되도록 최선을 다해 코드를 작성해야 했고 공유할 때 효과가 있길 바랬다.

  따라서 프로그래머들이 쉽게 사용하도록 OS는 소프트웨어 프로그램과 하드웨어 주변 장치의 중재자로서의 단계를 밟았다. 보다 구체적으로 장치 드라이버(Device drivers)라고 불리는 API를 통해 소프트웨어 추상화를 제공했다. 이를 통해 프로그래머는 표준화된 메커니즘을 사용하여 입출력 하드웨어(Input&Ouput; I/O)와 대화할 수 있게 되었다. 예를 들어 프로그래머는 "print(highscore)"와 같은 함수를 호출하면, OS는 그것을 종이 위에 쓰기 위해 작업을 수행할 것이다.

 

  1950년대 말, 컴퓨터는 너무 빨라져서 종종 유휴 상태가 되었다. 프린터와 펀치 카드 리더기 같은 느린 기계들을 기다리는 경우가 많았다. 프로그램이 I/O에서 차단되는 동안, 값비싼 프로세서는 단지 쉬고 있는 것이다. 50년대 후반 영국의 맨체스터 대학에서는 아틀라스라는 슈퍼 컴퓨터로 작업을 시작했다. 세계 최초의 슈퍼 컴퓨터이다. 사람들은 슈퍼 컴퓨터를 최대한 활용할 수 있는 방법이 필요했다. 해결책으로 1962년에 끝난 Atlas Supervisor라고 불리는 프로그램이 있다. 이 운영 체제는 프로그램을 자동으로 로드했을 뿐 아니라 초기의 일괄 처리 시스템처럼 동시에 여러 개의 프로그램을 단일 CPU에서 실행할 수도 있었다. OS는 영리한 스케줄링을 통해 작업했다.

  Atlas에서 게임을 실행한다고 가정해보자. Print(highscore)라는 함수를 호출하여 Atlas에게 highscore라는 변수를 종이에 인쇄하도록 지시한다. 그 함수 호출은 수천 클럭 사이클에 해당하는 시간이 걸릴 것이다. 왜냐하면 기계식 프린터가 전자 CPU에 비해 느리기 때문이다. 따라서 I/O가 끝날 때까지 기다리는 대신, Atlas는 프로그램을 절전 모드로 전환하고 다음 대기 중인 실행할 준비된 다른 프로그램을 선택하여 실행한다. 나중에 프린터는 Atlas에 "highscore"값의 인쇄를 마쳤다고 보고한다. Atlas는 프로그램을 실행 준비가 된 것으로 표시하고, 어느 시점에서 CPU에 다시 실행되도록 예약하고 print문 다음의 코드 행으로 계속 진행한다.

  이 방법으로 Atlas는 다른 프로그램이 데이터를 인쇄하고 있고 또 다른 프로그램이 펀치 테이프의 데이터를 판독하고 있는 동안에 CPU에서 계산을 실행하는 프로그램을 실행할 수 있다.

 

  Atlas의 기술자들은 이 아이디어를 두 배로 늘렸다. 4대의 테이프 판독기, 4개의 종이테이프 펀치, 8개의 자기 테이프 드라이브로 컴퓨터를 완성했다. 이로 인해 많은 프로그램이 하나의 CPU에서 한꺼번에 진행되어 시간을 공유할 수 있었다. 이 기능은 운영 체제에서 가능하며, 멀티 태스킹(Multitasking)이라고 부른다.

 

  멀티 태스킹 기능이 있음에도 하나의 컴퓨터에서 여러 프로그램을 동시에 실행하는 데에는 큰 걸림돌이 있다. 각각의 프로그램은 메모리가 필요할 것이고, 다른 프로그램으로 전환할 때 그 프로그램의 데이터를 잃을 순 없다. 해결책은 각 프로그램에 자체 메모리 블록을 할당하는 것이다.

  예를 들어, 컴퓨터가 만 개의 메모리 주소를 가지고 있다고 가정해보자. 프로그램 A가 0~999까지, 프로그램 B가 1000~1999까지 할당된 메모리 주소를 얻을 수 있다. 여기서 프로그램 A가 더 많은 메모리를 요구하면, 운영 체제는 요청을 승인할 수 있는지 여부를 결정하고, 승인한다면 다음에 할당할 메모리 블록을 결정한다. 그러면 프로그램 A가 0~999까지, 그리고 2000~2999까지의 메모리 블록을 쓰게 된다.

  이러한 유연성은 뛰어나지만 단점이 있다. 실제 프로그램에서는 메모리 전체에 수십 개의 블록이 할당되어 흩어져 있을 수 있다. 이것은 프로그래머가 계속 추적하기에 매우 혼란스러울 것이다. 만약 하루의 끝에서 합쳐져야 할 판매 데이터의 긴 목록이 있을 수 있지만 이 목록은 다양한 메모리 블록에 걸쳐 저장될 것이다. 이 복잡성을 숨기기 위해 운영 체제는 메모리 위치를 가상화한다.

 

  가상 메모리(Virtual Memory)를 사용하면 프로그램은 메모리가 항상 주소 0에서 시작되어 단순하고 일관되게 유지된고 가정할 수 있다. 그러나 실제 컴퓨터 메모리의 물리적 위치는 운영체제에 의해 추상되고 숨겨져 있다. 이전 예제에서 프로그램 B를 예로 들어보자. 주소 1000~1999의 메모리 블록이 할당되어 있다. 하지만 프로그램 B는 0~999의 주소를 가진 것으로 나타난다.

OS와 CPU는 가상-실제 메모리를 다시 자동으로 매핑하여 처리한다. 따라서, 프로그램 B가 메모리 위치 42를 요청하며 실제 주소 1042를 읽게 된다. 이 메모리 주소의 가상화는 예시의 프로그램 A에서 더욱 유용해진다. 예시에서 프로그램 A는 서러 분리된 두 개의 메모리 블록이 할당되어 있다. 이것 역시 프로그램 A에게는 보이지 않는다. 프로그램 A에게는 2000개의 연속적인 메모리 블록의 주소가 할당된 것으로 보이게 된다. 프로그램 A가 메모리 주소 999를 읽으면 동시에 물리적 메모리 주소 999로 매핑된다. 그러나 프로그램 A가 바로 다음 값이 주소 1000을 읽으며, 이는 뒤에서 실제 메모리 주소 2000으로 매핑된다.

 

  이 메커니즘을 통해 프로그램은 메모리 크기를 유연하게 사용할 수 있다. 이를 동적 메모리 할당(dynamic memory allocation)이라고 한다. 프로그램에게는 메모리 주소가 연속적인 것처럼 인식된다. 모든 것을 단순화하고 동시에 여러 프로그램을 실행하는 운영 체제에 엄청난 유연성을 제공한다.

 

  각 프로그램에 자체 메모리를 할당하는 또 다른 장점은 서로로부터 더 잘 격리된다는 점이다. 버그가 있는 프로그램이 잘못되면 최악의 경우 버그가 있는 프로그램의 메모리만 버리는 것으로 해결이 가능하다. 이 기능을 메모리 보호(Memory Protection)라고 한다. 이는 바이러스와 같은 악의적인 소프트웨어로부터 보호하는 데에도 유용하다. 예를 들어, 일반적으로 한 프로그램이 모든 메모리를 읽거나 수정할 수 있는 기능을 원하지 않는다. 그러니까, 이메일에 그러한 종류의 액세스 권한이 있으면 악성 소프트웨어가 사용자를 대신하여 전자 메일을 보내고 개인 정보를 도용할 수 있다.

 

  Atlas는 가상 메모리와 메모리 보호 기능을 모두 가졌다. 그리고 이러한 기능을 지원하는 최초의 컴퓨터 및 OS였다. 1970년대까지 컴퓨터는 충분히 빠르고 저렴했다. 대학교와 같은 기관은 컴퓨터를 구입하여 학생들이 사용할 수 있게 하였다. 기관의 컴퓨터는 여러 프로그램을 한 번에 돌리기에 충분히 빠르지도 않았고, 동시에 여러 사용자가 서로 상호작용적 접근을 할 수 없었다. 그저 대형 컴퓨터에 연결되는 키보드와 화면만으로 그 자체에 처리능력은 포함되지 않고, 터미널을 통해 작업을 수행하였다. 보통 냉장고 크기의 컴퓨터에 50개의 터미널이 연결되어 50명의 사용자가 사용 가능했다.

 

  이제 운영 체제는 여러 프로그램뿐만 아니라 여러 사용자를 다룰 수 있게 되었다. 아무도 컴퓨터 자원을 먹어치울 수 없도록, 운영 체제는 시간 공유 기능(Time-sharing)을 제공하도록 개발되었다. 개별 사용자는 시간 공유를 통해 컴퓨터 프로세서, 메모리 등의 일부분만 활용할 수 있었다. 컴퓨터가 너무 빠르기 때문에 단지 리소스의 1/50만 차지해도 개인이 많은 작업을 완료하기엔 충분했다.

 

  초기의 가장 영향력 있는 시간 공유 운영 체제는 1969년 나온 Multics(Multiplexed Information and Computing Service)이다. Multics는 처음부터 안전하도록 설계된 최초의 운영 체제였다.

 

  개발자는 아무 사용자나 그들이 접근해선 안 되는 데이터에 접근하는 것을 막았다. 이와 같은 기능은 Multics가 그 당시 많은 양인 1메가바이트 메모리를 사용했고, 실제로 복잡했음을 의미한다. 그것은 그 당시 컴퓨터 전체 메모리의 절반일 수도  있는 양으로 단지 OS를 실행하기 위한 것만으로 사용되었다. Multics의 연구원 중 한 명인 Dennis Ritchie는 "상업적 성공을 거둔 Multics가 명백히 잘못한 것들 중 하나는 어떤 면에서 지나치게 내구성이 강한 것이다. 그 안에는 너무 많은 것이 있었다."라고 말했다.

  Dennis와 다른 Multics 연구원인 Ken Thomson은 스스로 파업을 하고 유닉스(UNIX)라는 새로운 운영 체제를 구축했다. 그들은 OS를 두 부분으로 분리하고자 했다. 첫 번째는 커널(kernel)이라고 부르는 I/O를 다루는 기능인 메모리 관리, 멀티 태스킹과 같은 OS의 핵심 기능이다. 두 번째 부분은 추가적으로 제공되지만 커널이 아닌 프로그램과 라이브러리 같은 유용한 도구들이었다. 작고 군살 없는 커널을 만드는 것은 의도적으로 일부 기능만 남겨두는 작업이었다.

  다른 Multics 개발자인 Tom Van Vleck는 "Dennis에게 Multics에서 작성한 코드의 절반이 오류 복구 코드라는 것은 언급했었다."라고 회상했다. 그는 "우리는 유닉스에서 모든 것들을 빼버렸다. 오류가 발생하면 패닉이라고 하는 루틴을 갖게 됩니다. 이것이 호출될 때 기계가 충돌하고, '재부팅하십시오'라고 홀을 질주합니다."라고 하였다. 커널 패닉이라는 말은 여기에서 비롯되었다. 말 그대로 커널이 충돌할 때, 복구할 수단이 없기 때문에 "패닉"이라는 기능을 호출한다.

 

  원래는 "Panic"이라는 단어를 출력하고 무한 루프로 들어가는 작업을 했다. 이 단순함은 저렴하고 다양한 하드웨어에서 유닉스가 돌아갈 수 있다는 것을 의미했고, Dennis와 Ken이 일하는 벨 연구소에서 널리 사용되었다. 유닉스를 사용하여 자신의 프로그램을 만들고 실행하는 개발자가 많아지면서, 기여되는 도구 수도 증가했다.

  1971년에 출시된 직후, 다른 프로그래밍 언어용과 워드프로세서용 컴파일러를 만들었고, 1970년대와 80년대의 가장 인기 있는 OS 중 하나가 되었다. 동시에 1980년대 초반까지, 기본 컴퓨터의 비용은 개인이 구입할 수 있을 정도로 하락했고, 개인 또는 가정용 컴퓨터라고 불렸다. 이것들은 대학, 기업 및 정부에서 볼 수 있는 중앙컴퓨터보다 훨씬 더 간단했다. 그들의 운영 체제는 똑같이 단순하게 있어야 했다. 예를 들어, Microsoft의 디스크 운영 체제 또는 MS-DOS는 160 킬로바이트에 불과했지만, 이름에서 알 수 있듯이, 하나의 디스크에 맞출 수 있었다.

  1981년에 처음 출시된 MS-DOS는  비록 멀티 태스킹과 메모리 보호 기능은 부족했지만 초기 가정용 컴퓨터로 가장 널리 사용되었다. 이러한 기능의 부족은 프로그램이 시스템과 정기적으로 충돌할 수 있고 할 것임을 의미한다. 사용자는 자신의 컴퓨터를 다시 껐다 켤 수 있는 절충안이 있었다.

  Microsoft가 1985년에 처음 출시한 Windows의 초기 버전은 1990년 전반에 걸쳐 OS를 지배했지만 이조차도 강력한 메모리 보호 기능이 없었다. 프로그램이 잘못 수행되면 전체 운영 체제를 중단시킬 정도로 심각하게 다운되었다는 신호화 함께 죽음의 블루 스크린이 뜬다. 다행히 최신 버전은 더 나은 보호 기능을 제공하여 대개의 경우 충돌을 일으키지 않는다.

 

  오늘날 컴퓨터는 Mac OS, Windows, Linux, iOS 및 안드로이드와 같은 최신 운영 체제를 실행한다. 비록 우리가 가지고 있는 컴퓨터가 종종 한 사람만 사용하는 경우가 많더라도, 모든 OS는 멀티 태스킹, 가상 메모리, 메모리 보호 기능을 갖추고 있다. 따라서 한 번에 많은 프로그램을 실행할 수 있다. 웹브라우저에서 유튜브를 보면서, 포토샵으로 사진을 편집하고, 음악 재생을 하며 파일을 다운로드할 수 있다. 이는 운영 체제에 대한 수십 년간의 연구 및 이러한 프로그램을 저장할 적당한 메모리가 없으면 불가능하다.

728x90
반응형

'컴퓨터공학 > 기초' 카테고리의 다른 글

파일 & 파일 시스템  (0) 2022.09.04
메모리(Memory) & 저장 장치(Storage)  (0) 2022.08.28
집적 회로와 무어의 법칙  (0) 2022.08.20
소프트웨어 공학  (0) 2022.08.18
앨런 튜링 Alan Mathison Turing  (0) 2022.08.15

댓글