Task Management

CLKH64 OS/12장 2013. 1. 24. 01:49 Posted by 알 수 없는 사용자

 

IA-32 프로세서는

- Task의 상태를 저장하거나,

- 실행을 위해서 Task를 디스패칭 하고

- Task를 다른 Task로 스위칭 하는 기능을 제공한다.

 

운영체제가 보호모드에 있다면, 모든 프로세서 실행은 Task와 같이 일어난다. 심지어 간단한 시스템조차도 최소한 하나의 Task는 정의해야 하고, 더 복잡한 시스템의 경우에는 프로세서가 지원하는 Task Management 기능을 이용해 멀티 태스킹 어플리케이션을 지원할 수 있을 것이다.

 

하나의 Task는 다음과 같이 두개의 파트로 구성되어 있다.

- Task Execution Space

: TES(줄여서)는 코드 세그먼트, 스택 세그먼트 그리고 하나 혹은 그 이상의 데이터 세그먼트로 구성되어 있다. 만약 운영체제나 Executive가 프로세서가 지원하는 Privilege-level Protection을 사용한다면, TES는 각 privilege level별로 독립된 stack을 제공한다.

- Task-State Segment

: TSS는 TES를 구성하는 세그먼트들을 구체적으로 지정하고, Task의 상태 정보를 저장하기 위한 공간을 제공한다. 만약 멀티 태스킹 시스템이라면, TSS는 task-linking 메커니즘을 제공할 것이다.

 

Task는 매핑된 TSS 를 위한 세그먼트 셀렉터에 의해서 식별된다. 다시말해서, 세그먼트 셀렉트를 통해 TSS, 즉 Task가 결정된다.

Task가 실행을 위해 프로세서에 로드될때, 해당 TSS 를 위한

- 세그먼트 셀렉터
- 베이스 어드레스
- 리밋
- 세그먼트 디스크립터

가 Task Register에 로드된다.

그리고 만약 해당 Task를 위한 페이징이 구현되어 있다면, 해당 Task에 의해 이용되는 페이지 디렉터리의 베이스 어드레스가 CR3에 로드된다.

 

 

위 그림에서 볼 수 있듯이, 시스템이 Privilege-Level 보호 메커니즘을 사용한다면, TSS는 권한별 스택을 제공할 수 있다.

 

[Task의 실행]

소프트웨어나 프로세서는 실행을 위해 Task를 다음중 한가지 방법을 이용해 디스패치 할 수 있다.

- CALL 명령을 통한 Task의 명시적 Call.

- JMP 명령을 통한 Task의 명시적 Jump.

- Interrupt-Handler Task로의 암시적 Call(프로세서에 의한)

- Exception-Handler Task로의 암시적 Call(마찬가지로)

- EFLAGS.NT(14)가 세팅되어 있을때 IRET을 통한 리턴.

(참고로 NT는 Nested Task의 약자이다.)

 

Task 디스패칭을 위한 이런 방법들은 TSS나 Task-Gate를 가리키는 세그먼트 셀렉터와 같이 쓰여 디스패치 될 Task를 지정한다.

CALL, JMP 명령을 통해 Task를 디스패칭 한다면, Selector는 TSS를 바로 가리키거나(TSS디스크립터를) TSS를 위한 셀렉터를 포함하는 Task-gate를 가리킬 수 있다.

Interrupt나 Exception을 다루기 위해 Task를 디스패칭 한다면, 해당 인터럽트나 예외를 위한 IDT 엔트리는 반드시 Task-gate를 포함하고 있어야 한다. 그리고 이 Task-gate는 Interrupt, Exception-handler TSS를 위한 셀렉터를 반드시 포함하고 있어야 한다.

 

Task가 실행을 위해 디스패치되면 Task 스위칭이 현재 돌아가는 Task와 새롭게 디스패치된 Task 사이에서 일어난다. 현재 실행중인 Task의 실행 환경, 즉 Context가 그 자신의 TSS에 저장되고, Old Task의 실행은 멈추게 된다. 새롭게 디스패치된 New Task의 Context가 프로세서에 로드되고, 새롭게 로드된 EIP로부터 New Task가 실행된다.

만약 현재 실행중인 Calling Task가 디스패치되는 Called Task를 호출한다면, Calling TSS를 위한 세그먼트 셀렉터가 Called Task의 TSS에 저장된다. 이는 Called Task가 끝났을때 Calling Task로 돌아가는 Link-back을 제공하기 위함이다.

모든 IA-32 프로세서에서, Task는 재귀적이지 못한다. 다시말해서, 자기 자신을 호출할 수 없다.

 

인터럽트나 예외 또한 Handler Task로 스위칭 될 수 있다. 그리고 다시 Interrupted Task로 돌아올 수도 있다. 또한 Interrupt 중 일어나는 Interrupt 또한 다룰 수 있다.

프로세서는 LDT 스위칭 또한 제공한다. 이를 통해 각 Task가 LDT-based 세그먼트에 대한 다른 Logical-Physical Address Mapping을 가질 수 있다.(이건 뭔 개소린지 모르겠음. 아마도 그냥 각기 다른 Task가 각기 다른 LDT를 가질수 있다는 뜻인거 같은데.)

CR3 또한 Task 스위칭 과정에서 다시 로드되는데, 이를 통해 프로세서는 각 Task가 자신만의 페이지를 가질 수 있도록 한다. 이러한 보호 기능은 Task들이 독립적일 수 있게 만든다.

Privilege-Level 보호 기능을 사용하더라도, 위에서 언급한 보호 메커니즘이 사용하지 않는다면, 프로세서는 Task간 보호를 제공할 수 없다. 예를들어 레벨 3의 Task는, 다른 레벨 3의 Task가 사용하는 코드 세그먼트를 사용하고 데이터, 스택 세그먼트를 Corrupt 시킬 수 있다.

멀티 태스킹을 위해서 Task Managment 기능을 사용하는건 Optional이다. 다시말해서 멀티태스킹은 소프트웨어적으로 구현될수 있다. 즉, 소프트웨어적으로 구현된 다수개의 Task 는 하나의 IA-32 Task위에서 실행되기도 한다.

그리고 내가 알기로 윈도우가 이렇게 자체적인 멀티태스킹 기능을 사용한다. 즉, 윈도우는 프로세서가 제공하는 태스크 스위칭을 이용하지 않는다.

 

[Task Management Data Structures]

- Task-State Segment

- Task-gate Descriptor

- TSS Descriptor

- Task Register

- EFLAGS.NT(14)

 

위에서도 언급 했었지만, 보호모드라면 TSS와 그것을 가리키는 TSS 디스크립터를 최소한 하나는 정의해야 하고, 그 TSS를 위한 세그먼트 셀렉터를 LTR명령어를 이용해 Task Register에 로딩 해야 한다.

 

 

[TSS]

 

 

 

[TSS Descriptor]

TSS는 GDT에만 존재할 수 있다. LDT나 IDT에는 있을 수 없다.

TI Flag가 세팅된 셀렉터, 즉 LDT로의 접근을 위한 셀렉터로 TSS 접근하려 한다면 #GP.

TSS를 위한 셀렉터를 TR이 아닌 세그먼트 레지스터로 로드하려 해도 #GP

 

Busy 플래그는 Task가 바쁜지를 나타낸다. Busy Task는 현재 돌아가고 있거나, (인터럽트에 의해) 중지된(Suspended) Task다.

Type 1001은 Inactive Task를 나타내고, Type 1011은 Busy Task를 나타낸다.

프로세서는 이 Busy Flag를 해당 Task가 Interrupted 되었는지 아닌지를 판단하기 위해 사용한다.

하나의 Task당 하나의 Busy Flag만 존재해야 한다는걸 보장하기 위해, 모든 TSS는 그것을 가리키는 단 하나의 TSS 디스크립터를 가져야 한다.

그리고 32비트이고 G플래그가 0일때, TSS 디스크립터의 리밋은 0x67보다 같거나 커야 한다. 이게 최소의 TSS 사이즈다.

프로그램이나 프로시져가 TSS에 접근할때, 해당 프로그램이나 프로시져의 CPL은 TSS의 DPL보다 당연히 낮거나 같아야 한다.

일반적으로 TSS 디스크립터는 3미만의 값으로 DPL이 세팅되어있으나, 멀티 태스킹 시스템에서는 몇몇 TSS 디스크립터는 DPL이 3일수도 있다.

 

책에도 나와있지만, 64비트 모드에서는 Task스위칭이 지원되지 않는다. 그럼에도 TSS 디스크립터는 존재하고, 16바이트로 확장됐다.

 

 

[Task-Gate Descriptor]

 

 

 

 

 

[Task Register]

 

 

[Task Linking]

 

 

 

[Shared Memory]

 

 

 

 

 

'CLKH64 OS > 12장' 카테고리의 다른 글

GDT 32비트, 64비트 모든 세그먼트 구현 코드  (0) 2013.01.27
I/O Bitmap  (0) 2013.01.27
System Descriptor  (1) 2013.01.22