컴퓨터공학의 기초가 되는 cs지식을 되새기면서 이 후 있을 기술면접을 대비 하고자한다.
일단 운영체제의 구조가 어떻게 발전되어갔는지를 보면서 알아볼 필요가 있다.
예전 DOS 시절 운영체제에서는 자원의 효율성이 굉장히 떨어졌었다.
예전에는 메모리에 여러 가지 작업들이 올라가지 못하였다.
예를 들어 수행해야 할 작업-1과 작업-2가 있다고 가정해보자.
작업-1은 CPU를 사용한 후 I/O 장치를 사용하고,
작업-2는 CPU만을 사용하는 작업이라고 할 때,
예를 들어 작업-1이 먼저 수행이 되면서 CPU를 사용하고 I/O를 사용하는 동안 CPU는 놀고 있음에도 불구하고 작업-2는 메모리에 올라가있지 않기 때문에 작업-1의 전체적인 작업이 끝나기 전까지 작업을 시작하지 못하였다. (I/O 장치를 사용할 때도 마찬가지입니다. )
이러한 유연하지 않은 구조는 컴퓨터 전체의 효율성을 떨어뜨렸다.
그래서 생각해낸 것이 CPU와 I/O를 바쁘게 하자!이고 그것이 바로 Multiprogramming이다.
Multiprogramming은 여러 작업들이 동시에 메모리에 올라가게 됩니다.
그리고 위와 같이 작업-1이 수행되는 동안 CPU가 대기 상태로 들어가고 I/O를 수행할 때 작업-2는
대기 상태인 CPU를 사용하게 함으로써 유연성을 제공하여 효율성을 높이는 방법이다.
반대로 I/O가 대기 상태일 때는 I/O가 필요한 작업에게 그 자원을 할당해준다.
Multiprogramming에도 단점이 있었다.
그것은 바로 작업들마다 자원의 사용에 시간 차이가 생기기 때문이다.
예를 들어 작업-1이 CPU를 사용하고 I/O를 사용하게 되면 CPU는 작업-2에게 할당되어 작업-2는 CPU를 사용하게 된다.
하지만 만약 작업-1의 I/O 사용시간이 길어지면 작업-2가 CPU를 이용한 작업을 끝내도 I/O 작업으로
들어가지 못하고 계속 대기하게 된다. 그럼 이때도 역시 위와 마찬가지의 CPU 자원의 낭비가 일어나게 되는 것이다.
이러한 낭비는 효율성을 떨어뜨리는 결과를 가져온다.
그래서 등장한 것이 Multitasking이다.
Multitasking은 Multiprogramming의 논리의 확장이라고 보면 된다.
각각의 작업에 시간을 부여하고 CPU를 작업하다가 그 시간이 지나가면 다른 작업에게 CPU 자원을 할당해준다.
그러므로 위와 같은 시간 지연으로 인한 낭비를 줄일 수 있으며 주어 진 시간은 굉장히 짧아서 빈번한 switching이 발생하게 된다.
운영체제는 이전 포스팅에서 설명하였듯이 interrupt(event)-driven 방식이다.
운영체제는 한 작업의 error로 인해 자원을 계속해서 점유하는 일과같이 효율성과 컴퓨터의 동작을 저해하는 행위를
보호해야 할 수단을 필요로 한다. 그러한 방법에는 크게 두 가지가 존재한다.
조건은 H/W의 지원이 요구된다. (시스템을 보다 안전하게 하는 것이 목표)
이 방법은 Mode-Bit라는 것을 필요로 하는데, Mode에는 Kernel Mode와 User Mode 두 가지가 있다.
프로그램이 메모리에 올라가서 작업들을 수행할 때 명령어들을 하나씩 읽어와 수행하게 되는데
하지만 사용자가 Kernel 상의 작업, 즉 컴퓨터의 Core에 해당하는 작업들을 직접 건드려 명령하고 수행을 하게 된다면
자칫 잘못하다는 시스템 전체에 큰 악영향을 끼칠 수 있게 된다. 그것을 방지하고자 이러한 방법을 도입하게 되었다.
각각 명령어에 Mode-bit를 심어 해당 명령어의 Mode-bit와 현재 시스템 상의 Mode-bit가
같을 시에만 해당 명령어를 수행하게끔 하는 것이다.
예를 들어
printf("출력");
위의 코드는 C에서 콘솔 창에 특정 문구를 출력하는 코드이다.
모니터를 통해 콘솔 창에 출력하는 행위는 I/O를 이용하여 출력을 하게 된다.
이러한 I/O 작업은 OS만 접근이 가능해야 하는데
위의 함수의 내용을 열어보면 여러 가지 명령어들이 있고 그중에 INT 80이라는 명령어를 찾아볼 수 있다.
위의 명령어는 특수 명령어로서 현재 Mode를 바꿔주는 역할을 한다.
즉 이전까지 수행되던 명령어들은 User-Mode였다면 화면에 출력하기 위해서는 Kernel-Mode가 필요하므로
위의 명령어를 통해 Mode를 Kernel-Mode로 변환 후 I/O 장치에 출력을 하는 명령을 OS가 내리게 된다.
그리고 함수가 끝날 때는 다시 User-Mode로 돌아게 된다.
이러한 bit를 바꾸는 행위를 System-Call이라고 한다. 굉장히 중요한 개념이다.
이렇게 Kernel에서 수행되어야 하는 몇 가지 중요한 명령어들이 있다. 위에서 언급한 운영체제의 Services들이다.
그 예를 들어보자면
1. Turn off interrupts
2. Access I/O devices
3. Set value of timer
등이 있고 이외에도 여러 가지 명령어들이 있다.
System Call이 일어나게 되면 앞선 포스팅에서 Interrupt Vector Table과 Interrupt Vector Routine의 동작원리와 같이
해당 System Call에 대한 번호를 Table에서 찾아 Routine을 실행하게 된다. 이러한 작업은 운영체제에서 일어나게 된다.
밑의 사진은 System Call의 이해를 조금 더 도울 수 있을 것 같다.
Timer는 이름에서와 같이 Timer는 infinite loop 나 자원의 독점을 막는다.
Timer는 특정 시간이 지나면 Interrupt를 발생시키고 운영체제는 그 시간을 감소시키면서 Interrupt를 기다린다.
운영체제는 Timer가 끝난 작업을 종료시키고 또한 실행되기 전 Scheduling 작업 전에 Timer를 작동시킨다.
운영체제의 하는 일
1. Process management
2. Memory management
3. Storage management
4. Protection and Security
Program vs Process
Program은 현재 Memory에 올라와 있는 Process들 중 실행 중인 Process이다.
Process는 CPU time, Memory, files, I/O 등 여러 자원을 필요로 하다.
운영체제의 Process Management
운영체제의 Memory Management
사용자에게 도움을 주는 Services
시스템의 운영의 효율성을 제공하는 Services
System Call
직접적으로 사용하지 않으며 High-Level Language로 작성된 API가 제공된다.
각 System Call에 대한 번호와 루틴은 Table의 형태로 저장된다.
루틴이 끝난 뒤 System Call의 상태와 결괏값을 반환한다.
System Call의 종류
References (참고 자료)