멀티테스킹을 이해하기 위해서는 보호모드(Protected Mode)를 먼저 이해하여야한다.
*보호모드(Protected Mode)란
보호모드는 Intel 80286부터 도입되기 시작하였으며, 차차 발전된 보호모드는 80386에 이르러 현재와 같은 완성된 모습이 된다.80286의 초기 보호모드는 24 Bit Address Bus를 사용하여 물리 메모리(Physical Memory)의 사용 영역이 16mb가 되었다.그 후, 보호모드에서는 CPU가 제공하는 모든 기능과 명령어를 사용할 수 있는데, 후에 32Bit Address Bus를 통해 4GB의 물리 메모리의 사용 영역을 갖게된다. 메모리 보호기능(Memory Protection), 페이징(Paging) 등을 통하여 효율적인 구현이 가능하다.인터럽트, 예외처리, 태스크 스위칭(Task Switching) 등은 보호모드에서 지원하는 기능을 활용 하는 기능이다.
보호모드의 레지스터와 자료구조. (인텔 펜티엄 III CPU 기준)
*멀티테스킹
멀티테스킹은 복수의 어플리케이션이 동시에 작동하고 있는 상태를 뜻한다. 하나의 프로세서에서 복수의 어플리케이션이 동시에 움직이는 것은 양자컴퓨터가 아닌이상 구현키 힘들다. 우리가 현재 사용하는 멀티테스킹은 우리 눈에는 동시에 작동하는 것 처럼 보이지만, 실제로는 다르다.
위의 그림은 세로줄은 어플리케이션 수를 의미하며, 가로줄은 시간을 의미한다. 즉, 멀티테스킹은 속임수이다. 완전 동시 작동이 아니라는 것을 뜻한다. 여러가지 다중 프로세스를 인간이 눈치채지 못할정도로 분할 하여, 각개 프로세스를 조금씩 진행한다. 위의 그림을 살펴봤을 때, 1번 프로세스를 조금 진행하고, 2번 프로세스를 조금 진행하는식으로, 4번 프로세스까지 반복한 후,다시 1번 프로세스를 조금씩 진행하는 방식을 사용한다. 이것은 하나의 시간대를 공유하며 진행하는 방식으로, 시분할 방식(Time Sharing)을 사용한다. 순차적으로 프로세스를 하나하나 동작시키는 것과 시분할 방식과는 프로세싱에 있어서 시간차이가 날 수밖에 없다. 이것은 시분할 방식 시에, 계속해서 전환되는 시간(Task Switching - Interrupt Time) 때문인데, 대신 사용자가 두 작업을 동시에 실행 할 수있다는 장점을 갖고, 전환되는 시간의 간격(Switching Interval)이 매우 짧기 때문에, 동시에 보이는 것처럼 보이는 것(Illusion of parallelism)뿐이다. 이것에 파이프라인과 슈퍼스칼라 구조가 더해져, 더욱 부드러운(즉, 고속의) 멀티테스킹이 구현되기에 이른다.
*TSS란?
보호모드에서는각 태스크(Task)별로 TSS(Task State Segment)를 관리한다.
TSS란 레지스터의 내용이 메모리에 저장되는 것을 말하며, 16비트와 32비트가 있다. 태스크 스위칭을 위해 정보기록과 출납을 담당한다.
OS의 시스템커널에서는 이 TSS를 사용하기위하여 세가지 절차를 밟아야 한다:
1. TSS 디스크립터 엔트리(Descriptor Entry)를 GDT(Global Descriptor Task)에 생성
2. 세그멘트 셀렉터(Segment Selector)에서 해당 세그먼트를 TR(Task Register)과 함께 로드
3. 메모리의 TSS에 필요한 정보를 기록
*TSS는 시스템 안정화의 목적으로 접근하기 쉬운 메모리에 배치되어야한다.
*GDT란 프로그램이 실행되는 동안 사용되는 메모리 영역을 정의하기 위한 Intel기반에서 쓰이는 데이터 구조(Data Structure)을 말한다.
*TR은 현재 태스크의 TSS를 가르키는 셀렉터(selector)이며, 각 TSS는 GDT에서 TSS Descriptor로 기술되며, TR은 이중 현재의 TSS의 Descriptor를 가르킨다. 내부적으로 세그먼트의 기준 주소(Bass Address)와 세그먼트 리미트(Segment Limit)를가지고 있지만, 외부에서는 셀렉터(Selector)값만을 참조 할 수 있다.
Descriptor Table - GDT와 LDT. 그리고 셀렉터
TSS에는 하나의 태스크의 상태 - 일반 register, segment register, flag, EIP, stack segment selector, stack pointer, LDT selector, page directory base address 등 - 이 저장이 되며 태스크 스위칭(Task Switching)이 일어날 때, 일어나기 전의 상태를 자동으로 이곳에 정리하며, 새로운 차후 TSS에 다시 복구된다.
TSS가 32비트일 경우, 구조체를 이용한 프로그래밍은 다음과 같이 성립한다.
1 : struct TSS32 {
2: int backlink, esp0, ss0, esp1, ss1, esp2, ss2, cr3;
3: int eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
4: int cs, es, ds, ss, fs, gs;
5: int ldtr, iomap;
6: };
*TSS는 위처럼 int형으로 26개가 모여, 104바이트가 된다. (4바이트씩)
*2 행의 backlink 부터, cr3는 레지스터의 내용이 아닌 테스크의 설정에 관한 내용이므로, 태스크 스위칭이 일어나도 값은 불변한다.(backlink는 예외적으로 바뀌는 경우가 있다.)
*3 행은 32비트 레지스터이며, 4행은 16비트 레지스터이다.(레지스터 비트별 표기법 참조)
*세그먼트 레지스터는 16비트로 구성되어있지만, TSS안에서는 int(=DWORD)로 구성되어있다.
*5 행의 ldtr과 iomap은 설정에 관한부분으로, 2 행과 같은 역할이다. 따라서 태스크 스위칭이 일어나도 값은 불변하다.
*그림참조 : Intel Processor Strutcure Information