멀티 프로그래밍과 멀티 태스킹에 대해 들어본 적이 있을 것이다. 이번엔 이 2가지 방식에 대해 알아보도록 한다.
우선 몇가지 사실에 대해 알고 넘어가야한다.
1. 실행 가능한 프로그램은 메모리에 올라와있다.
2. 프로세스는 여러 큐들에 의해 관리된다. (Ready, Sleep)
3. (CPU는 single core라 가정했기에) 한 번에 하나의 프로세스만 작동(Run)한다.
멀티 프로그래밍의 작동 과정은 다음 그림과 같다.
(노란색 원은 큐를 뜻한다.)
Ready 상태의 프로세스를 CPU가 한가할 때 CPU가 실행(dispatch)해서 Run 상태로 만든다.
Run 하고 있다가 IO 명령이 발생하면 Sleep 상태가 된다.
다시 Ready 상태의 프로세스를 하나 골라서 dispatch한다.
Sleep 상태에서 IO 명령이 끝났다면 Ready 상태로 보낸다.
한 프로세스가 모든 작업이 끝났다면 Zombie 상태가 된다.
Zombie 상태에서 일종의 처리를 하고 Terminated 상태로 보낸다.
길어보이지만 그림만 봐도 이해할 수 있을정도로 간단하다.
그런데 간단한만큼 문제점이 있다.
앞서 우리는 OS의 목표 중 한 가지로 공정함(fairness)를 뽑았다. 위 방식의 경우 Run하고 있는 프로세스에 IO 명령이 없다면 해당 프로세스를 모두 마칠 때까지 독점하게 될 것이다.
이러한 문제를 해결하기 위해 멀티 태스킹(=Time Sharing) 방식이 등장한다.
멀티 태스킹의 작동 과정은 다음 그림과 같다.
멀티 프로그래밍과 유사하지만 Run 도중에 일정한 시간(time slice 또는 time quantum)이 지나면 time out이 되서 다시 Ready 상태가 된다.
그냥 간단히 프로세스당 가질 수 있는 최대한의 시간을 할당하는 것이다. 이 때 할당하는 시간이 너무 길다면 멀티 프로그래밍과의 차이점이 없어지고, 너무 짧다면 context switch가 너무 많이 발생해 성능이 저하된다. 1
OS Structure만 쓰고보니 너무 짧아서 Hardware Protection부분도 함께 쓴다. 어차피 어느 정도는 연관이 있으니..
요즘 OS는 멀티 태스킹방식을 사용하기 때문에 자원들을 공유하는 것을 피할 수가 없다. (여러 프로세스들이 메모리를 공유하기에)
프로세스에 의해 자원들을 공유하기 때문에 문제가 발생할 수 밖에 없다. OS는 이러한 문제들에 대해 책임을 져야한다.
그래서 다음과 같은 원칙을 하나 세운다.
"권한이 있는 프로세스만 자원들에 접근할 수 있다."
어떤 방식으로든 위 원칙을 위반하게 되면..
OS로 인터럽트를 발생시킨다.(trap이라 한다.)
트랩이 발생하게 되면 다음과 같은 ISR(인터럽트 서비스 루틴)을 실행한다.
OS는 화면에 적절한 메시지를 표시해주고, 위반된 프로세스를 종료시키고, 유저들이 디버깅할 수 있도록 메모리와 레지스터의 내용들을 준다.
그렇다면 트랩이 발생하는 가장 대표적인 경우를 알아보자.
컴퓨터가 일을 하고 있다는 것은 곧 프로그램이 돌아가고 있다는 것이다.
이 때 프로그램의 종류는 유저 프로그램과 OS 프로그램이 있다.
앞서 우리는 다음 그림을 보았었다.
이 때 Applications가 유저 프로그램, Kernel이 OS 프로그램이 돌아가는 위치라고 생각하면 된다. 유저 프로그램이 돌아가고 있는 시간은 유저 모드, OS 프로그램이 돌아가고 있는 시간은 OS모드(또는 커널 모드, 슈퍼바이저 모드)라고 한다. (이러한 모드의 판별을 위해 CPU안에 1bit의 플립 플롭이 있다.)
조금 더 설명해보자면 OS 프로그램들은 하드웨어를 다룰 수 있고, privileged라고 선언한다. 그런데 만약 유저모드에서 privileged 명령어들을 실행한다면 트랩이 발생하게 된다.
그러니까 다시 말해 유저는 IO 명령을 직접 사용할 수 없다.
위 말에서 당연히 의문이 생길 수 있다. 운영체제를 공부한다면 당연히 C언어와 같은 언어 1가지쯤은 공부했을 것이다. C언어로 예를 들자면 printf, scanf와 같은 IO 명령을 사용해본 적이 있을 것이다.
printf나 scanf를 사용할 때 stdio.h 헤더파일을 선언한 후 사용했을 것이다. 이 때 이 헤더파일 안에 printf나 scanf 함수가 write나 read 함수로 정의되어 있음을 확인할 수 있다. (write나 read 함수는 OS 모드의 시스템 콜이며, 이 부분은 뒤에서 조금 더 자세히 설명하도록 하겠다.)
메모리 Protection의 경우 한 메모리에 여러 프로세스들이 있기에 다른 프로세스의 데이터를 사용하려하거나 명령어를 실행하려하면 안된다.
그래서 base와 limit을 둔다. base는 시작, limit은 크기를 뜻한다.
예를 들어 base = 3072, limit = 1024라면 3072 ~ 4096 사이에만 접근이 가능하다.
이 때 base와 limit 레지스터는 하드웨어이기 때문에 OS의 privileged 명령어에 의해 load 된다.
CPU Protection은 더 간단하다.
유저 프로세스가 무한 루프에 걸렸을 때 time out을 걸어서 쫓아내 버린다.
또는 timer를 둬서 너무 장기 체류하는 프로세스는 쫓아내 버린다.
여기까지가 Protection인데 Protection과 Security에 대해서 잘 구별할 수 있어야한다. Security는 내외부 침입에 대한 공격에 대한 것을 Security라 한다. 보호와 보안에 대해 생각해보면 될 듯 하다.
- 참고로 현재는 보통 약 5ms정도이다. [본문으로]
'운영체제' 카테고리의 다른 글
프로세스 (0) | 2020.07.11 |
---|---|
시스템 콜 (0) | 2020.07.07 |
메모리 (0) | 2020.07.06 |
interrupt의 도착 이후 (0) | 2020.04.13 |
OS의 가동 및 interrupt (0) | 2020.04.06 |