Win2k_driver_ch_14

Download Report

Transcript Win2k_driver_ch_14

ISLab Flash Team
Ch 14. System Thread
Contents
1.
2.
3.
4.
5.
시스템 쓰레드의 정의와 사용
쓰레드 동기화
디스패쳐 객체 사용하기
예제코드 : 쓰레드 기반의 드라이버
Summary
ISLab Flash Team
Ch 14. System Thread
2
Made By Povolon
ISLab Flash Team
1. 시스템 쓰레드의 정의와 사용
Thread 란?
• 실행의 단위
• 독립적인 프로그램 카운터와 개별적인 CPU레지스터의 집
합을 가지는 하드웨어 컨텍스트를 유지
• CPU를 점유하기 위해 우선순위 값을 가짐
• 사용자 모드 Thread와 커널 모드 Thread를 가짐
• 시스템 Thread는 커널 모드에서만 접근 가능
=> 사용자모드 context가 없고 사용자주소공간에 접근불가
ISLab Flash Team
Ch 14. System Thread
4
Made By Povolon
Thread를 사용해야 하는 경우
• 디바이스의 동작이 느리고 자주 접근 되지 않는 경우
• 디바이스가 상태변화를 하기 위해서 너무 오랜 시간이 소
요되고 드라이버 상태 변화가 일어나기를 기다려야 하는
경우
• 디바이스가 하나의 작업을 마치기 위해서 여러 번의 상태
변화를 해야 하는 경우
• 디바이스가 상태 변화를 알리기 위한 인터럽트를 발생시
키지 않고 드라이버가 지정된 시간 동안 디바이스를 정기
적으로 폴링 해야 하는 경우
ISLab Flash Team
Ch 14. System Thread
5
Made By Povolon
System Thread의 생성
•
Function Prototype for an PsCreateSystemThread Routine
NTSTATUS
IRQL == PASSIVE_LEVEL
PsCreateSystemThread
Parameter
Description
OUT PHANDLE ThreadHandle
새로운 쓰레드에 대한 핸들
IN ULONG DesiredAccess
드리이버가 만든 쓰레드일 경우 0
IN POBJECT_ATTRIBUTES Attrib
드라이버가 생성했으면 NULL
IN HANDLE ProcessHandle
드라이버가 생성했으면 NULL
OUT PCLIENT_ID ClientId
드라이버가 생성했으면 NULL
IN PKSTART_ROUTINE StartAddr
쓰레드의 진입지점
IN PVOID Context
쓰레드 루틴에 전달할 Context
Return value
• STATUS_SUCCESS : 생성시
• STATUS_XXX
ISLab Flash Team
Ch 14. System Thread
6
Made By Povolon
System Thread의 소멸
• 시스템 쓰레드는 드라이버가 메모리로 부터 없어질 때 반드시 제거해
야함
• 강제적으로 쓰레드를 소멸시킬 수 없음
( Event 객체를 활용)
•
Function Prototype for an PsTerminateSystemThread Routine
NTSTATUS
IRQL == PASSIVE_LEVEL
PsTerminateSystemThread
Parameter
Description
IN NTSTATUS ExitStatus
종료될때의 상태값
Return value
• STATUS_SUCCESS : 제거시
ISLab Flash Team
Ch 14. System Thread
7
Made By Povolon
Thread 우선 순위
• 시스템 쓰레드는 실시간 범위 중에서 낮은 값
( LOW_REALTIME_PRIORITY)를 가져야 함
• 실시간 쓰레드
– 할당된 TimeOut값이 없으므로 자발적으로 block 거나 더 높은
우선순위의 쓰레드에 의해 선점될 경우만 Switching이 일어남
• 드라이버 는 라운드-로빈 스케줄링 방식에 의존하지 않음
ISLab Flash Team
Ch 14. System Thread
8
Made By Povolon
System Worker Threads
•
짧은 작업을 수행하기 위해서 콜백 기법을 통해 사용
1. WORK_QUEUE_ITEM 구조체를 메모리에 할당
2. 드라이버에있는 콜백 함수를 WORK_QUEUE_ITEM과 연
결 ( ExInitializeWorkItem 루틴)
3. 시스템 작업 대기열에 WORK_QUEUE_ITEM을 요청하는
블록을 삽입
•
실행시간이 많이 걸리는 작업은 다른 드라이버의 작업 실
행을 지연 시킬 수 있으므로 독립적인 드라이버 쓰레드를
사용해야 함
ISLab Flash Team
Ch 14. System Thread
9
Made By Povolon
ISLab Flash Team
2. 쓰레드 동기화
시간 동기화
•
지정한 시간이 지날때까지 쓰레드의 실행을 멈추는것
(Timer 객체 or KeDelayExecutionThread 함수)
•
Function Prototype for an KeDelayExecutionThread Routine
NTSTATUS
IRQL == PASSIVE_LEVEL
KeDelayExecutionThread
Parameter
Description
IN KPROCESSOR_MODE
WaitMode
드리이버는
Kernel Mode
IN BOOLEAN bAlertable
드라이버는 false
IN PLARGE_INTEGER Interval
절대나 상대적인 시간
Return value
• STATUS_SUCCESS : 대기완료
ISLab Flash Team
Ch 14. System Thread
11
Made By Povolon
일반적인 동기화
•
Dispatcher 객체를 기다림 ( signaling되지 않은 dispatcher객체 )
•
Funtion Prototype for an KeWaitForSingleObject Routine
NTSTATUS KeWaitForSingleObject
Parameter
Description
IN PVOID Object
Pointer to Driver Object
IN KWAIT_REASON Reason
드라이버는 Executive
IN KPROCESSOR_MODE WaitMode
드라이버는 Kernel Mode
IN BOOLEAN Alertable
드라이버는 False
IN PLARGE_INTERGER Timeout
절대 or 상대적인 Timeout값
Return value
• STATUS_SUCCESS
• STATUS_ALERTED
• STATUS_TIMEOUT
ISLab Flash Team
Ch 14. System Thread
12
Made By Povolon
일반적인 동기화 (cont.)
•
Funtion Prototype for an KeWaitForMultipleObjects Routine
NTSTATUS KeWaitForMultipleObjects
Parameter
Description
IN ULONG Count
기다릴 객체의 개수
IN PVOID Object[]
디스패쳐 객체에 대한 포인터 배열
IN KWAIT_REASON Reason
드라이버는 Executive
IN KPROCESSOR_MODE WaitMode
드라이버는 Kernel Mode
IN BOOLEAN Alertable
드라이버는 False
IN PLARGE_INTERGER Timeout
절대 or 상대적인 Timeout값
IN PKWAIT_BLOCK WaitBlocks[]
이 동작을 위한 대기 블록의 배열
Return value
• STATUS_SUCCESS
• STATUS_ALERTED
• STATUS_TIMEOUT
ISLab Flash Team
Ch 14. System Thread
13
Made By Povolon
일반적인 동기화 (cont.)
•
•
•
쓰레드는 Timeout값을 지정하여서 다시 깨울 수 있음
Multiple일 경우 쓰레드가 기다릴 수 있는 객체 수 제한
( MAXIMUM_WAIT_OBJECTS )
THREAD_WAIT_OBJECTS 객체 수만큼 기다릴 수 있음
•
PASSIVE_LEVEL 이나 DISPATCH_LEVEL에서 호출
•
DISPATCH_LEVEL에서는 Timeout값이 0
=> 시그널링 된 객체를 정기적으로 확인하기 위한 기법
ISLab Flash Team
Ch 14. System Thread
14
Made By Povolon
ISLab Flash Team
4. Dispatcher 객체 사용하기
Dispatcher Object
• 메모리에 지속적으로 상주( Nonpaged space )
• Device Extension or Controller Extension에 공간 할당
• 사용 전 초기화 ( KeInitializeXxx )
ISLab Flash Team
Ch 14. System Thread
16
Made By Povolon
Event Object
• Signaling or Nonsignaling상태로 반드시 설정 되어야 하
는 객체 (KEVENT로 할당)
• Signaling으로 설정해서 다를 쓰레드의 발생을 부추길 수
있다
Thread B
Thread A
설정
EVENT
Thread C
Thread D
• 알림 이벤트
-> Signaling되기를 기다리는 모든 쓰레드를 깨움
• 동기화 이벤트
-> 하나의 쓰레드만 깨움
ISLab Flash Team
Ch 14. System Thread
17
Made By Povolon
Event Object (cont.)
•
사용 시기
이벤트 객체를 조작하는 함수들
호출 함수
IRQL
이벤트 생성 KeInitializeEvent
PASSIVE_LEVEL
이름을 갖는 IoCreateSynchronizationEvent
이벤트 생성 IoCreatNotificationEvent
PASSIVE_LEVEL
KeSetEvent
이벤트 상태
KeClearEvent
수정
KeResetEvent
<=DISPATCH_LEVEL
타이머를 대 KeWaitForSingleObject
기
KeWaitForMultipleObjects
PASSIVE_LEVEL
이벤트 상태
KeReadStateEvent
질의
<=DISPATCH_LEVEL
ISLab Flash Team
Ch 14. System Thread
18
Made By Povolon
드라이버간 이벤트 공유
• 이벤트 공유를 위한 포인터의 전달 과 메모리 상주 문제
• IoCreateSynchronizationEvent 와
IoCreatNotificationEvent 함수를 이용하여 이름을 갖는
Event를 생성
• 동일한 Event name을 가지면 동일한 Event객체의 포인터
를 얻을 수 있음
• CreateEvent 처럼 동작함
ISLab Flash Team
Ch 14. System Thread
19
Made By Povolon
드라이버간 이벤트 공유 (cont.)
•
IoCreateXxxEvent
– KEVENT 객체의 메모리 할당은 시스템에서 함
– 할당된 메모리의 핸들이 return됨
-> 핸들에서 포인터를 얻어내야함
1. ObReferenceObjectByHandle 함수를 호출
-> 객체 포인터를 얻고, 참조 카운트를 증가
2. 핸들이 필요하지 않게 되면 핸들을 해제( ZwClose 함수)
3. 이벤트 객체가 필요하지 않게 되면 ObDereferenceObject 함수
를 호출하여 참조 카운트를 감소, 이벤트 객체를 삭제
ISLab Flash Team
Ch 14. System Thread
20
Made By Povolon
Mutex Object (Mutual Exclusion)
•
•
•
•
오직 하나의 쓰레드에서만 소유될 수 있음
소유하면 Nonsignaling -> 사용가능 하면 Signaling
공유 자원에 대한 상호 배타적인 접근을 조절
KMUTEX 객체는 Nonpaged space에 할당
0
counter 1
소유 요청
사용가능 소유 소유 요청
Thread A
종료
or
Block
해제
counter 1
소유 요청 소유
사용가능 Thread B
Mutex
Thread C
counter 0
1
소유 요청
Blocked
Blocked counter 1
Thread D
Blocked
ISLab Flash Team
Ch 14. System Thread
21
Made By Povolon
Mutex Object (cont.)
•
뮤텍스를 초기화하면 초기 상태는 signaling
•
사용 시기
Mutex 객체를 조작하는 함수들
호출 함수
IRQL
뮤텍스 생성
KeInitializeMutex
PASSIVE_LEVEL
뮤텍스 소유권 요구
KeWaitForSingleObject
KeWaitForMultipleObjects
PASSIVE_LEVEL
뮤텍스 소유권 포기
KeReleaseMutex
PASSIVE_LEVEL
뮤텍스 상태 질의
KeReadStateMutex
<=DISPATCH_LEVEL
•
뮤텍스를 모두 해제를 하고 드라이버는 커널모드에서 사용자 모드로
이동
ISLab Flash Team
Ch 14. System Thread
22
Made By Povolon
Semaphore Object
•
•
•
•
카운트를 관리하는 디스패쳐 객체
Count가 0보다 크면 Signaling
0이면 Nonsignaling
KSEMAPHORE객체를 메모리에 할당
대기
대기
수행
Thread A
종료
or
Block
해제
대기
수행
Semaphore
count
수행
Thread C
2
0
1
대기
Thread B
Blocked
Blocked
Thread D
Blocked
ISLab Flash Team
Ch 14. System Thread
23
Made By Povolon
Semaphore Object (cont.)
•
사용 시기
Semaphore 객체를 조작하는 함수들
호출 함수
IRQL
세마포어 생성
KeInitializeSemaphore
PASSIVE_LEVEL
세마포어 감소
KeWaitForSingleObject
KeWaitForMultipleObjects
PASSIVE_LEVEL
세마포어 증가
KeReleaseSemaphore
<=DISPATCH_LEVEL
세마포어 상태 질의
KeReadStateSemaphore
Any
ISLab Flash Team
Ch 14. System Thread
24
Made By Povolon
Timer Object
•
•
•
•
타임 아웃 값을 가지는 디스패쳐 객체
타이머가 시작된 후 타임아웃이 될때까지 Nonsignaling
타임아웃이 되면 Signaling
KTIMER객체를 메모리에 할당
Thread A
Clock
SetTimer
Wait
Timer
Blocked
Continue
ISLab Flash Team
Ch 14. System Thread
25
Made By Povolon
Timer Object (cont.)
•
사용 시기
Timer 객체를 조작하는 함수들
호출 함수
IRQL
타이머 생성
KeInitializeTimerEx
PASSIVE_LEVEL
타이머를 한번 시작
KeSetTimer
<= DISPATCH_LEVEL
타이머를 반복 시작
KeSetTimerEx
<= DISPATCH_LEVEL
타이머 정지
KeCancelTimer
<= DISPATCH_LEVEL
타이머를 기다림
KeWaitForSingleObject
KeWaitForMultipleObjects
PASSIVE_LEVEL
세마포어 상태 질의
KeReadTimerState
<= DISPATCH_LEVEL
ISLab Flash Team
Ch 14. System Thread
26
Made By Povolon
Thread Object
•
•
시스템 쓰레드도 디스패쳐 객체
쓰레드가 소멸되면 Signaling
– 드라이버가 종료 될 때 쓰레드 객체를 기다림
1. ObReferenceObjectByHandle 함수를 호출
-> 객체 포인터를 얻고, 포인터 참조 카운트를 증가
2. 핸들이 필요하지 않게 되면 핸들을 해제( ZwClose 함수)
-> 객체의 핸들 참조 카운트를 감소
3. 이벤트 객체가 필요하지 않게 되면 ObDereferenceObject 함수
를 호출하여 포인터 참조 카운트를 감소, 쓰레드 객체를 삭제
ISLab Flash Team
Ch 14. System Thread
27
Made By Povolon
뮤텍스의 변형 (1)
•
고속 뮤텍스 ( Fast Mutex )
– 반복적인 소유권 요청을 불가
– 보호를 요하는 한 개 이상의 데이터 항목과 연관된
FAST_MUTEX 타입의 객체
– 데이터 항목에 접근하려면 FAST_MUTEX의 소유권을 얻어야함
•
고속 뮤텍스를 조작하는 함수들
사용 시기
호출 함수
IRQL
뮤텍스 생성
ExInitializeFastMutex <= DISPATCH_LEVEL
고속 뮤택스 소유권 요구
ExAcquireFastMutex
<= DISPATCH_LEVEL
고속 뮤텍스 소유권 포기
ExReleaseFastMutex
<= DISPATCH_LEVEL
ISLab Flash Team
Ch 14. System Thread
28
Made By Povolon
•
뮤텍스의 변형 (2)
실행부 자원 ( Executive resources )
– 하나의 쓰레드에 의해 독점적으로 소유 가능
– 여러 쓰레드가 읽기 접근을 공유 가능
• 실행부 자원을 조작하는 함수들
사용시기
호출 함수
IRQL
생성
ExInitializeResourceLite
PASSIVE_LEVEL
획득
ExAcquireResourceExclusiveLite
ExAcquireResourceSharedLite
ExTryToAcquireResourceExclusiveLite
ExConvertExclusiveToSharedLite
<= DISPATCH_LEVEL
해제
ExReleaseResourceforThreadLite
<= DISPATCH_LEVEL
질의
ExIsResourceAcquiredSharedLite
ExIsResourceAcquiredExclusiveLite
<= DISPATCH_LEVEL
삭제
ExDeleteResourceLite
<= DISPATCH_LEVEL
ISLab Flash Team
Ch 14. System Thread
29
Made By Povolon
Deadlock
•
뮤텍스나 세마포어를 사용하여 발생
1. 타임아웃 인자를 사용하여 기다리는 시간을 제한
2. 동일한 순서로 자원을 요청함
할당
Resource X
대기
Thread A
Thread B
대기
Resource Y
할당
Acquire X
Acquire X
Y
Acquire Y
Acquire Y
X
…
…
Release X
Release Y
Release Y
Release X
ISLab Flash Team
Ch 14. System Thread
30
Made By Povolon
ISLab Flash Team
4. 예제 코드 : 쓰레드 기반의 드라이버
샘플 드라이버의 구조
PsCreateSystemThread
I/O request
KeReleaseS
emaphore
Dispatch 루틴
Semaphore
Count
Thread
0
1
Wake up
IRP
ISR 루틴
KeWaitFor
Singleobject
Wait
IRP
Queue
Wait
Wake up
DPC 루틴
Event
Signaling
Nonsignaling
KeWaitFor
Singleobject
ISLab Flash Team
Ch 14. System Thread
32
Made By Povolon
샘플 드라이버의 객체 및 함수
•
DEVICE_EXTENSION
– 드라이버에서 정의된 모든 데이터 구조체를 포함
– 드라이버가 시스템 쓰레드와 작업 대기열을 관리하기 위해
•
•
필요한 작업자 쓰레드 객체
•
어댑터 객체를 얻었을 때 알릴 이벤트 객체
•
IRP 큐를 관리하는 세미포어와 스핀락 객체
AddDevice routine
– I/O 요청을 처리 하기 위해 사용 되는 쓰레드 객체, 작업 대기열
객체 및 동기화 객체를 초기화
– 드라이브를 load할때 한번 호출됨
ISLab Flash Team
Ch 14. System Thread
33
Made By Povolon
샘플 드라이버의 객체 및 함수
•
DispatchReadWrite routine
–
–
–
–
디바이스에 대해 읽거나 쓰고자 하는 사용자 요청에 응답
전송할 데이터가 있는 지 확인
IRP를 종료되지 않았다는 표시를 한 뒤 작업 대기열에 삽입
세마포어가 쓰레드를 동작 할 수 있게 count를 증가
(KeReleaseSemaphore)
ISLab Flash Team
Ch 14. System Thread
34
Made By Povolon
Thread.cpp 모듈
•
주 쓰레드 함수와 쓰레드를 관리 하기 위해 필요한 루틴
포함
•
WorkerThreadMaine 함수
– IRP를 처리하는 엔진
– 드라이버의 Context를 받아서 DEVICE_EXTENSION의 작업 대
기열에서 I/O 요청을 가지고 오고 데이터 전송 작업을 수행
1. 자신 ( 쓰레드 ) 는 사용자 보다 높은 우선순위로 설정
2. RemoveDevice함수에서 멈추라는 지시가 있을 때까지 리턴이
없이 무한 루프로 동작
3. IRP처리를 위해서 semaphore가 유효할때까지 대기
( KeWaitForSingleObject )
4. 실제 IRP처리를 실시(PerformDataTransfer)하고, IRP를 해지한
뒤, 다른 IRP요청을 처리하기 위해 루프를 돔
ISLab Flash Team
Ch 14. System Thread
35
Made By Povolon
Thread.cpp 모듈
•
KillThread 함수
– 특정 디바이스 객체와 관련된 쓰레드를 중지 하라는 통보역활
– 목적 쓰레드가 정지 할때 까지 멈추어서 기다림
1. 정지 플래그를 설정
2. 쓰레드가 살아 있는 지 확인( KeReleaseSemaphore )
3. 쓰레드가 끝나기를 기다림 ( KeWaitForSingleObject )
ISLab Flash Team
Ch 14. System Thread
36
Made By Povolon
Thread.c 모듈
•
I/O작업을 수행하는 루틴을 포함
•
쓰레드의 데이터 전송 루틴이 시작할 수 있도록 이벤트
객체를 설정
•
PerformDataTransfer 함수
– DMAC의 역할을 수행함
– 한번에 데이터를 다 처리 할 수 없다면 데이터 전송을 나눔
– 작업이 완료 될때까지 계속 수행
1. I/O 방향을 설정 , 예약 값을 설정, CPU캐쉬를 플러쉬
2. 데이터 분할 전송의 크기를 계산 해서 분할 전송 처리
( PerformSynchromousTransfer ) 처리후 예약 정보를 수정
3. 분할 전송이 끝날때까지 I/O동작을 수행
4. 처리량을 조절하면서 수행 후 IRP를 반환
ISLab Flash Team
Ch 14. System Thread
37
Made By Povolon
Thread.c 모듈
•
AcquirAdapterObject 와 AdapterControl
– 어댑터 객체의 소유권을 얻기 위한 동기화 기법을 쓰레드에 제
공
•
AcquireAdapterObject
– 시스템 쓰레드의 컨텍스트에서 실행 되기 때문에 일정한 시간
간격을 멈추고 기다릴 수 있게 구현
1. 어댑터 객체를 요청하기 위해 DISPATCH_LEVEL에서 수행
2. 이벤트 객체를 세팅하는 AdapterControl 루틴을 위해 정지하고
기다림, 어댑터 객체를 다른 디바이스에서 사용 못하도록 어댑
터에 대한 이벤트 객체를 기다림 ( KeWaitForSingleObject )
•
AdapterControl
– 맵핑 레지스터에 대한 핸들을 저장하고 데이터 전송을 설정
ISLab Flash Team
Ch 14. System Thread
38
Made By Povolon
Thread.c 모듈
•
PerformSynchronousTransfer 함수
– 한번의 데이터 전송 작업을 수행
– 전송이 끝날때까지 리턴 되지 않음
– 디바이스 인터럽트 발생 여부를 확인 하기 위해 이벤트를 사용
1. DMA컨트롤러를 설정하고 디바이스를 구동
2. I/O 처리 완료 인터럽트에 대한 이벤트를 기다림
( KeWaitForSingleObject )
3. 어댑터 객체 캐쉬의 데이터를 플러쉬, 디바이스의 에러 체크
ISLab Flash Team
Ch 14. System Thread
39
Made By Povolon
Thread.c 모듈
•
DpcForIsr
– 디바이스가 인터럽트를 발생 시키면 인터럽트 처리 루틴은 하드
웨어 상태값을 저장하고 DPC를 요청
– 이벤트 객체를 시그널링 상태로 변경
– PerforSynchronousTransfer 함수가 실행됨
ISLab Flash Team
Ch 14. System Thread
40
Made By Povolon
ISLab Flash Team
Summary
Summary
• 다른 작업 들과 병렬로 특정 작업을 수행
• 드라이버 내에 시스템 쓰레드를 사용 하는 방법
• 다중 쓰레드 기법을 적절하게 활용 할 것
ISLab Flash Team
Ch 14. System Thread
42
Made By Povolon