저번 문서에서는 Kernel에서 System Thread 사용하는 방법에 대해서 알아보았습니다.
이번에는 System Thread와 조금 다른 WorkItem 루틴에 대해서 알아보겠습니다.
드라이버 PsCreateSystemThread함수를 사용해 System Thread를 만들면 해당 스레드는 드라이버 것이므로
그 안에서 무한 반복문을 돌려서 써버린다던지 해도 상관이 없습니다.
하지만 WorkItem 루틴은 동작 방식이 조금 다릅니다.
WorkItem 루틴은 IO관리자가 준비한 몇 개의 System Thread들 중 아무 스레드에서 호출이 되는 루틴입니다.
그렇기 때문에 한 WorkItem 루틴이 종료를 하지 않고 계속 반복문 같은 것을 돌려서 CPU를 사용하게 되면 다른 드라이버들이 WorkItem 루틴을 사용할 기회를 잃게 되는 것입니다. 그러므로 WorkItem 루틴은 할일만 딱 마치고 바로 종료를 해주는게 좋습니다.
일단 이 루틴을 왜 쓰는지 이유에 대해서는 나중에 보기로 하고 먼저 함수 정보들부터 봐보겠습니다.
WorkItem 루틴의 형태입니다.
IO_WORKITEM_ROUTINE WorkItem;
VOID WorkItem(
__in PDEVICE_OBJECT DeviceObject,
__in_opt PVOID Context
)
{ ... }
그리고 위 루틴을 호출하기 위해선 IoAllocateWorkItem, IoQueueWorkItem 두 가지 함수를 사용하게 됩니다.
PIO_WORKITEM IoAllocateWorkItem(
__in PDEVICE_OBJECT DeviceObject
);
WorkItem을 할당하는 함수입니다.
IRQL <= DISPATCH_LEVEL
첫번째 인자로는 디바이스 오브젝트 포인터가 들어가야 합니다.
디바이스 오브젝트 포인터는 IoCreateDevice 함수를 사용해 얻어주면 됩니다.
VOID IoQueueWorkItem(
__in PIO_WORKITEM IoWorkItem,
__in PIO_WORKITEM_ROUTINE WorkerRoutine,
__in WORK_QUEUE_TYPE QueueType,
__in_opt PVOID Context
);
WorkItem루틴을 호출하는 함수입니다.
IRQL <= DISPATCH_LEVEL
첫번째 인자는 위 함수에서 얻어온 IO_WORKITEM포인터를 넣으면 되고
두번째 인자는 WorkItem 루틴 포인터
세번째 인자는 해당 WorkItem 우선순위 입니다.
네번째는 나중에 파라미터로 사용 된답니다..
그러면 이 루틴을 언제 쓰면 좋을지에 대해서 알아보겠습니다.
잘 보시면 PsCreateSystemThread 함수와 다른점이 있는데
PsCreateSystemThread의 IRQL은 PASSIVE_LEVEL 입니다.
하지만 IoAllocateWorkItem, IoQueueWorkItem의 IRQL을 잘 보면 DISPATCH_LEVEL에서도 호출이 가능합니다.
훨씬 사용하는 시점이 System Thread보다 자유롭다는 것입니다..!!
저는 이 루틴을 이렇게 사용했었습니다.
보통 인터럽트를 처리할 때 빠른 속도를 위해 찌꺼기 코드??!! 같은 경우 DPC 루틴을 만들어서 DPC큐에 넣어둠으로서 처리를 할 수 있습니다. 이 때 DPC루틴이 실행되는 IRQL은 DISPATCH_LEVEL입니다. 즉, 안에서 스케쥴링이 일어날 만한 코드를 작성하면 안된다는 것입니다. 잘못 했다간 뻑이 나는거죠.
저는 DPC루틴에서 파일을 생성하기 위해 ZwCreateFile 함수를 호출을 하고 싶었습니다.
하지만 ZwCreateFile 함수의 IRQL은 PASSIVE_LEVEL입니다. DPC 루틴에서 호출했다간 파란화면 뿅뿅뿅 뜨겠지요..
그렇기 때문에 DPC루틴에서 호출가능한 WorkItem 루틴!!을 활용하는 것입니다.
WorkItem루틴은 System Thread에서 돌아가기 때문에 PASSIVE_LEVEL을 보장 받을 수 있습니다.
해결이 된거같군요. 아무튼 저는 이러한 이유로 WorkItem루틴을 사용했었습니다.
아마 다른 방법으로도 많이 사용이 되겠지요.
System Thread를 생성해서 쓸건지 WorkItem루틴을 쓸건지는 개발자의 몫인거 같습니다. 상황에 따라 잘 써야겠지요 ^^;
추가적으로 msdn에서 System Worker Threads에 대한 내용을 찾아보았습니다.
그 중에 마지막 단락을 보니 어느정도 답이 나와있었습니다.
대충 읽어보면 system worker threads는 리소스가 제한되어 있어서 worktiem 또는 workitemex루틴은 짧은 시간 동안만 동작을 할 수 있다고 나와있습니다. 만약에 하나의 workitem 루틴이 오랜시간 동안 실행을 해버린다거나 오랫동안 일을 끝마치지 않고 기다린다면 시스템은 데드록에 걸릴 수 있다고 나와있네요. 고로~! 만약에 드라이버에서 오랫동안
delayed processing을 사용할 거면 그냥 workitem루틴 대신에 PsCreateSystemThread를 사용해 그냥 하나의 스레드를 생성시켜서 거기서 작업을 하라는 것입니다. 어디서 workitem루틴의 적정 사용시간이 나와있는 문서를 본거 같은데 어디서 본건진 잘 모르겠고 적정 시간은 50 마이크로초 랍니다. 어디 나와있는지 아시는분은 알려주세요 :-)
'My Study > Programming&Theory' 카테고리의 다른 글
IDT Hooking 시 주의해야 할 점 (0) | 2010.12.25 |
---|---|
Named Pipe 간단한 예제 (4) | 2010.12.24 |
2가지 DPC 루틴 (2) | 2010.12.17 |
Hardware Manipulation ( Keyboard LED ) (0) | 2010.12.15 |
Driver에서 시스템 스레드 사용하기 ( 동기화 이벤트 오브젝트 ) (0) | 2010.12.14 |