프로그래머들이 종이에 연필로 프로그램을 적어 전산실에 주면 그 종이를 OMR 마킹하듯이 카드에 구멍을 뚫어 카드 리더기에 올린다. 읽은 내용은 메모리에 적재, 그다음 컴파일러가 들어있는 카드를 카드 리더에 올린다. 컴파일된 내용을 프린터에 출력한다. 이러한 과정을 Operator라는 직업을 가진 사람이 처리하였으며 별도의 운영체제는 없었다.
앞서 Operator가 했던 일들을 메모리 안에 작은 프로그램이 대체하도록 하였다. 이 프로그램을 Resident monitor라고 하며 최초의 운영체제이다. 메모리에 상주해서 일괄적인 일들을 한다고 해서 Batch Processing System 혹은 일괄처리 시스템이라고 부른다.
하드웨어(반도체)가 발전함에 따라 OS에도 큰 변화가 생겼다. 메모리는 Batch Processing OS와 User Program이 놓이는 구역으로 구분되었는데 User Program에는 하나의 프로그램이 올라갈 수 있었다. 아래 C언어 코드를 보자.
#include <stdio.h>
int main(void)
{
int i;
int count = 0;
printf("반복문 시작\n");
for(i = 0; i < 5; i++)
count++;
printf("result : %d", count);
}
변수값을 초기화하고 계산하는 과정은 CPU가 하고 출력은 IO 장치가 한다. 대략적으로 표현하면 이 프로그램은 CPU -> IO -> CPU -> IO 이런 순으로 동작한다. 하지만 User Program에는 하나만 올라갈 수 있으므로 IO 장치가 동작하고 있으면 CPU는 할 일이 없어서 IO가 마칠 때까지 쉬게 된다. 이를 Cpu가 IDLE상태에 있다고 한다. 보통 CPU는 빠르고 IO 장치 같은 프로그램들은 느리다. 따라서 CPU를 이렇게 방치하기에는 너무 아깝고 낭비가 심하다. 이를 해결하기 위해 메모리에 여러개의 프로그램을 올릴 수 있는 Multiprogramming system이 등장하였다. Multiprogramming system은 메모리에 여러 프로그램을 올리는 시스템이다. 메모리에 User program1, User program2, User program3 이런 식으로 할당하면 IO가 동작하는 와중에도 CPU는 쉬지 않고 계속 작동하게 된다. 이렇게 함으로써 CPU의 사용률을 대폭 향상시킬 수 있었다. 또한 Multiprogramming system이 등장하면서 생각해볼 이슈거리들도 생겼다. 대표적으로 CPU 스케줄링, 메모리 관리, 보호 등이 있는데 추후 자세히 배울 예정이다.
Degree of multiprogramming : 메인 메모리에 올라와 있는 프로세스의 수.
60~70년대 들어서 모니터, 키보드가 등장했다. 이로 인해 사용자와 대화가 가능해졌다. 컴퓨터는 매우 비쌌기에 하나의 컴퓨터에 여러개의 단말기들이 달려서 메모리를 공유하였다.
이러한 방식은 문제가 있었다. User 1이 실행되면 User 2, User 3은 아무것도 못한다. CPU가 1개라서 하나의 컴퓨터를 여러명에서 동시에 사용하면 기존의 MultiProgramming으로는 곤란하다. 어떻게 하면 한번에 여러 사람들이 동시에 사용할 수 있을까?
이를 해결하기 위해 등장한 개념이 Time Sharing이다. User 1 -> User 2 -> User 3 -> User 1 -> 이러한 방식으로 매우 짧은 시간을 주기로 스위칭하면 User들은 혼자 컴퓨터를 쓰는 것처럼 느낀다. 비록 컴퓨터는 1개지만 여러 사람들이 동시에 컴퓨터를 쓸수 있는 이러한 방식을 Time Sharing, 즉 시분할 시스템이라고 한다. Time Sharing이 등장함으로써 여러 기술들이 추가로 등장했는데 대표적으로 프로세서간 통신, 동기(synchronization), 가상메모리등이 있다. 추후에 자세히 배울 예정이다.
😆 현대 운영체제는 인터럽트를 기반으로 동작한다. 인터럽트에는 크게 하드웨어 인터럽트, 소프트웨어 인터럽트, 내부 인터럽트가 있다.
외부 하드웨어 장치에 의해 발생한 인터럽트를 하드웨어 인터럽트라고 한다. 마우스를 움직이고 클릭하는 과정을 통해 하드웨어 인터럽트에 대해 알아보자. 마우스를 움직이면 마우스에서 전기신호가 발생해서 인터럽트선을 통해 CPU에 전기 신호를 보낸다. CPU는 신호를 받으면 현재하던 일을 중지하고 프로그램 카운터(PC)가 OS 안의 interrupt service routine(ISR)으로 점프한다. interrupt service routine에는 인터럽트가 접수되었을때 그에 대응하여 특정 기능을 처리하는 기계어 코드가 들어있다. 여기서는 마우스가 움직이는 대로 모니터의 화면 커서를 옮기는 코드들을 수행한다. 그리고 마우스로 특정 프로그램을 더블 클릭하면 다시 인터럽트가 걸려 프로그램 카운터(PC)가 OS의 interrupt service routine으로 점프한다. 이번에는 더블 클릭하면 해당하는 프로그램을 하드디스크에서 찾아서 메인 메모리에 올리는 코드를 수행한다. 그리고 OS는 대기상태가 된다.
프로그램이 자신이 작성하지 않은 코드를 운영체제로부터 서비스받기 위해 발생시키는 인터럽트를 소프트웨어 인터럽트라고 한다. 프로그램의 어셈블리어 명령어 swi를 수행하면 소프트웨어 인터럽트가 걸린다. word 프로그램에서 Memo.docx파일을 읽어오는 과정을 알아보자. word는 하드디스크안의 내용(Memo.docx)을 가져오고 싶으면 swi 명령어를 통해 소프트웨어 인터럽트를 건다. 그러면 OS안의 인터럽트 서비스 루틴이 실행되어 하드디스크의 Memo.docx파일을 읽어 메모리로 가져온다. 인터럽트 작업이 끝나면 이전에 수행하던 프로세스의 작업을 마저 이어간다.
프로세스가 0으로 나누는 연산 등 불가능한 작업을 시도하거나, 자신의 메모리 영역 바깥을 접근하려는 시도를 할 때 이에 대한 처리를 위해 발생시키는 인터럽트를 내부 인터럽트라고 한다. 아래 c언어 코드를 보자.
#include <stdio.h>
int main()
{
int i = 5;
int j = 0;
int k = i / j;
printf("result : %d", k);
}
5를 0으로 나눌 수 없기 때문에 CPU는 내부적으로 인터럽트가 발생한거로 인지한다. 프로그램 카운터(PC)는 OS의 ISR로 점프한다. OS의 ISR에는 0으로 나누는 것을 처리하는 루틴들이 존재한다(프로그램 강제 종료). ISR이 수행되고 끝나면 원래 대기상태 또는 이전에 수행하던 프로세스로 돌아간다.
현재 사용하는 모든 운영체제는 인터럽트 기반이다. OS는 여러 코드들의 모음인데 이 코드들은 평상시에는 작동 안 하다가 인터럽트가 걸리면 작동한다.
다중 프로세서 시스템
CPU가 여러개 있는 시스템을 다중프로세서 시스템이라 한다. 다음과 같은 이점이 있다.
분산 처리 시스템
분산 시스템은 여러개의 컴퓨터가 동일한 작업을 처리하기 위해 네트워크상에서 서로 통신하며 협력하는 것이다.
실시간 시스템
특정 시간내에 계산을 반드시 끝내야 하는 시스템을 실시간 시스템이라 한다. 주로 공장 자동화, 군사, 항공, 우주 분야에서 사용된다.