2013. 1. 3. 18:04ㆍProgramming/윈도우 드라이버
Dispatching
- 실행 중인 한 스레드에서 다른 스레드로 실행을 전환하는 절차
Scheduling
- 프로세서에서 실행될 다음 스레드를 결정하는 절차
Quantum
- 특정 스레드가 CPU에서 실행하도록 정해진 시간
Pre-emption(선점)
- 현재 실행 중인 스레드의 우선 순위보다 더 높은 우선 순위를 가진 스레드가 실행할 준비가
되었을 때
IRQL
- 운영체제는 스레드가 실행하고 있는 도중에 인터럽트가 발생하면 이를 처리한다.
우리는 이를 당연하다고 여기지만 사실은 스레드에 의한 코드 실행과 인터럽트 발생으로 인한
코드 실행에는 각각 해당 중요도가 있으며 운영체제는 이들 중요도에 근거하여 우선적인 작업을
먼저 처리한다.
- 시스템에 존재하는 각 프로세서(CPU)는 자신만의 IRQL을 가진다.
만약 프로세서 A의 IRQL이 Clock 레벨이고, 프로세서 B의 IRQL이 DPC 레벨이라고 가정하자.
운영체제 입장에서는 프로세서 A는 매우 우선순위가 높은 긴박한 작업을 처리하고 프로세서 B는
그나마 덜 중요한 작업을 처리한다고 생각할 수 있다.
이런 상황에서 키보드 인터럽트(디바이스 IRQL)가 발생한다면 키보드 인터럽트를 처리하는
코드는 프로세서 A에서는 실행될 수 없고 프로세서 B를 선점하여 프로세서 B의 IRQL이 키보드
인터럽트에 해당하는 디바이스 IRQL로 상승된 다음에 키보드 인터럽트를 서비스 하게 된다.
- '스레드'는 일반적으로 PASSIVE_LEVEL의 쓰레드를 말한다.
또한 인터럽트가 '스레드'에 있는 CPU를 선점하게 되면 커널은 더 이상 스케쥴링을 진행하지
않는다.
즉, 스레드 퀀텀 시간은 CPU가 스레드를 실행하고 있는 동안 (PASSIVE_LEVEL)에만
유효하다.
PASSIVE_LEVEL
- 대부분의 스레드가 실행하는 IRQL이다.
IRQL의 관점에서는 유저 모드 스레드 실행이 우선 순위가 가장 낮은 행위로 인식한다.
이 레벨에서는 모든 윈도우 핵심 서비스를 호출할 수 있다.
예를 들어 페이지블(pageable) 메모리를 접근할 수 있고, 파일 I/O가 가능하며 스레드 블록도
가능하다.
커널 모드 프로그램을 작성할 때는 항상 DDK 문서를 참조하여 사용하는 커널 API가 현재 코드의
IRQL에서 사용 가능한지를 확인한다.
APC_LEVEL
- 커널모드에서 비동기 프로시저 호출을 처리할 때 재 진입을 제어하기 위해 커널 모드 루틴에
의해 사용된다.
예를 들어, 프로세서 A에서 ReadFile 함수를 비동기적으로 사용하여 파일 읽기를 파일 시스템
드라이버로 요청한다고 가정하자
파일 시스템 드라이버는 이 요청을 다시 디스크 드라이버로 보내고 디스크 드라이버는
하드웨어를 제어하여 적절한 위치에서 파일을 읽어내어 그 값을 파일 시스템 내의 버퍼로 전달할
것이다.
요청된 읽기 작업이 완료된 시점에서 파일 시스템은 읽기 요청을 한 유저 프로세스 A의 유저
주소 공간 내에 존재하는 버퍼로 데이터를 복사해야 한다.
하지만 이 작업을 하려면 현재 실행 중인 프로세서가 A인 경우에만 가능하다.
디스크 드라이버가 하드웨어로부터 데이터를 읽는 동안 프로세스 A가 컨텍스트 스위칭되어
프로세서 B가 현재 프로세스라면 이 작업을 할 수 없다.
따라서 파일 시스템은 APC 메커니즘을 통해 프로세스 A가 현재 프로세스 상태로 되거나
또는 되게 한 이후에 버퍼 복사 작업을 수행하도록 APC 메커니즘을 사용하여
운영체제에게 요청한다.
DISPATCH_LEVEL
- 두 가지 작업을 수행하기 위해 운영체제에서 사용된다.
즉, 지연된 프로시저 호출(DPC-Deferred Procedure Call) 처리와 디스패처(Dispatcher - 윈도우
스케줄러) 실행이 그것이다.
이 레벨에서 코드가 실행될 때 프로세서는 스레드를 전환하지 않는다.
이 레벨에서 실행되는 코드는 페이지블 메모리를 접근하거나 파일 I/O를 수행해서는 안된다.
즉 페이지 폴트를 유발하면 안된다.
그 이유는 DISPATCH_LEVEL에서 페이지 폴트 핸들러가 수행될 수 없기 때문이다.
또한 DISPATCH_LEVEL을 포함하여 상위 레벨에서 실행하는 코드는 이미 시그널되지 않은
디스패처 오브젝트를 대기할 수 없다.
즉 KeWaitForSingleObject같은 DDK 함수를 사용하면 안된다.
그 이유는 간단한데 대기하는 이벤트나 뮤텍스를 시그널 해 줄 다른 코드가 동작하기 위해서는
윈도우 스케쥴러(디스패처)가 실행되어야 하는데 현재 코드가 DISPATCH_LEVEL에서 수행되고
있으므로 이벤트나 뮤텍스를 시그널해 줄 코드가 실행될 기회가 없기 때문이다.
즉 현재 실행 중인 코드와 시그널 코드 모두가 같은 DISPATCH_LEVEL이라면 선점은
일어나지 않는다.
DPC(Deferred Procedure Call)
- 일반적으로 보다 높은 IRQL에서 추가적인 작업과 시간에 덜 민감한 작업 등을 처리하기 위해
요청된다.
예를 들어, DIRQL 레벨에서 할 수 없는 추가적인 작업이 필요한 경우 ISR은 DPC 메커니즘을
사용하여 작업을 계속 진행하도록 IoRequestDPC DDK 함수를 호출한다. 이로써 추가적인 작업은
이후에 DPC 콜백에 호출될 때 계속 진행된다.
DIRQL(Device IRQL)
- 디바이스로부터 발생하는 하드웨어 인터럽트를 사용하기 위해 사용된다.
대부분의 디바이스는 자신만의 정해진 IRQ 값을 가지고 있다.
이 IRQ 값을 근거로 하여 윈도우는 적절한 DIRQL 값을 결정한다.
디바이스 드라이버 작성자 관점에서 자신의 디바이스가 어떤 DIRQL 값을 가지는가는 중요하지
않다.
작성해야 할 인터럽트 서비스 루틴(ISR)이 DIRQL에서 동작한다는 사실과 이 레벨에서 코드를
작성할 때는 매우 제한적인 시스템 서비스 함수만을 사용할 수 있다는 점에 유의해야 한다.