You are on page 1of 371

LP TRNH H THNG

Bin tp bi:
Khoa CNTT HSP KT Hng Yn
LP TRNH H THNG

Bin tp bi:
Khoa CNTT HSP KT Hng Yn

Cc tc gi:
Khoa CNTT HSP KT Hng Yn

Phin bn trc tuyn:


http://voer.edu.vn/c/92c88426
MC LC

1. Bi 1: TNG QUAN V LP TRNH H THNG


1.1. Khi nim v lp trnh h thng
1.2. Tng quan v lp trnh h thng
1.3. Lch s v lp trnh h thng
1.4. Cu trc tng quan lp trnh h thng
2. Bi 2: CNG C LP TRNH H THNG
2.1. Cc ngn ng lp trnh
2.2. Gii thiu v C++
2.3. Gii thiu v Visual C++
3. Bi 3: THC HNH MT S BI TP C BN TRN C++
3.1. Thc hnh mt s bi tp c bn trn C++
4. Bi 4: C BN V CU TRC V DRIVER
4.1. Tm lc lch s cc b iu khin thit b
4.2. Tng quan v cc H iu hnh (An Overview of the Operating Systems)
4.3. Cc kiu Driver
4.4. Tng quan v qun l v kim tra danh sch
5. Bi 5: THC HNH MT S BI TP C BN TRN VC++
5.1. Thc hnh mt s bi tp c bn trn VC++
6. Bi 6: CC K THUT LP TRNH C BN
6.1. Mi trng lp trnh kiu Kernel Mode
6.2. Trnh by li (Li x l)
6.3. Qun l b nh (Memory Management )
6.4. Trnh by chui (String Handling)
6.5. K thut lp trnh hn hp (Miscellaneous Programming Techniques )
7. Bi 7: THC HNH MT S BI TP TRN VC++
7.1. Thc hnh mt s bi tp c bn trn Visual C++
8. Bi 8: LP TRNH GIAO TIP QUA CNG LPT
8.1. Gii thiu cng LPT
8.2. Cu trc cng LPT
9. Bi 9: THC HNH VI CC CHNG TRNH GIAO TIP QUA CNG LPT
9.1. Thc hnh vi cc chng trnh giao tip qua cng LPT
10. Bi 10: THC HNH VI CC CHNG TRNH GIAO TIP QUA CNG
COM
10.1. Gii thiu cng COM

1/369
10.2. Cu trc cng COM
11. Bi 11: THC HNH VI CC CHNG TRNH GIAO TIP QUA CNG
COM
11.1. Thc hnh vi cc chng trnh giao tip qua cng COM
12. Bi 12: VN NG B
12.1. Vn ng b ha nguyn mu (An Archetypal Synchronization Problem )
12.2. Mc yu cu Ngt (Interrupt Request Level )
12.3. Kha xoay vng (Spin Locks )
12.4. Cc i tng Kernel Dispatcher (Kernel Dispatcher Objects )
12.5. Mt s phng php ng b khc (Other Kernel-Mode Synchronization
Primitives )
13. Bi 13: THC HNH LP TRNH DRIVER C BN
13.1. Thc hnh lp trnh driver c bn
14. Bi 14: GI D LIU VO RA
14.1. Cc cu trc d liu (Data Structures )
14.2. Hng i yu cu Vora (Queuing IO Requests)
14.3. Hy b yu cu vora (Cancelling IO Requests )
14.4. Tm lc cc kch bn x l (SummaryEight IRP-Handling Scenarios)
15. Bi 15: THC HNH LP TRNH DRIVER CHO X L IRP
15.1. Thc hnh mt s bi lp trnh driver c bn
16. Bi 16: C V GHI D LIU
16.1. Cu hnh thit b ca bn (Configuring Your Device )
16.2. a ch mt B m d liu (Addressing a Data Buffer )
16.3. Cc cng v cc thanh ghi (Ports and Registers )
16.4. Phc v ngt (Servicing an Interrupt )
16.5. Truy nhp b nh trc tip (Direct Memory Access )
17. Bi 17: IU KHIN VO/RA V HM IU KHIN PLUG AND PLAY
17.1. Hm DeviceIoControl API (The DeviceIoControl API)
17.2. iu khin IRP MJ DEVICE CONTROL
17.3. Nhng thao tc bn trong iu khin IO (Internal IO Control Operations)
18. Bi 18: THC HNH LP TRNH DRIVER CHO IU KHIN VO/ RA
18.1. Thc hnh lp trnh driver cho iu khin Vora
19. Bi 19: TRNH IU KHIN CHO USB
19.1. Gii thiu cng USB
20. Bi 20: THC HNH IU KHIN QUA CNG USB
20.1. Thc hnh vi cc chng trnh v d iu khin qua cng USB

2/369
21. Bi 21: TRNH IU KHIN CHO HID
21.1. Nhng b iu khin cho thit b HID (Drivers for HID Devices )
21.2. Nhng m t bo co v nhng bo co (Reports and Report Descriptors )
21.3. Nhng iu khin nh HIDCLASS (HIDCLASS Minidrivers)
22. Bi 22: THC HNH LP TRNH HID
22.1. Thc hnh vi cc chng trnh v d iu khin cho HID
23. Bi 23: THC HNH LP TRNH DRIVER GIAO TIP CC CNG
23.1. Thc hnh mt s bi tp tng hp
24. TI LIU THAM KHO
24.1. Lp trnh h thng: Ti liu tham kho
25. MC LC
25.1. Lp trnh h thng: Mc lc
Tham gia ng gp

3/369
Bi 1: TNG QUAN V LP TRNH H
THNG
Khi nim v lp trnh h thng
Lp trnh h thng (hoc chng trnh h thng) l hot ng ca cc phn mm h
thng. u tin ch ra s khc bit tiu biu ca cc chng trnh h thng khi so
snh ti lp trnh ng dng l nhm vo lp trnh ng dng sn sinh phn mm
m cung cp nhng dch v ti ngi dng (v du: b x l vn bn), trong khi nhng
nh lp trnh h thng nhm vo vic sn xut phn mm m cung cp nhng dch v
ti phn cng my tnh (v d: phn mm chng phn mnh a). N cng yu cu mt
ln hn ca s thc phn cng.

4/369
Tng quan v lp trnh h thng
Nhng im c bit hn trong lp trnh h thng:

Nhng nh lp trnh s to nhng gnh vc v phn cng v mt s thuc tnh


khc ca nhng chng trnh chy trn h thng , v s thng khai thc
nhng thuc tnh (cho v d bi vic s dng mt gii thut m c bit
m hiu qu khi no c s dng vi phn cng c bit).
Thng thng mt ngn ng lp trnh cp thp hoc ting a phng ngn ng
lp trnh s dng l:
c th hot ng trong nhng mi trng ti nguyn bt buc
l rt hiu qu v c th thc hin mt t trn u
c mt th vin thc hin nh, hoc khng mi th
cho php trc tip v th m iu khin qua truy cp b nh v iu
khin chy trn
cho ngi lp trnh vit nhng phn ca chng trnh ngay tc khc
trn ngn ng assembly.
G ri c th l kh nu n l tht khng c th chy chng trnh trong mt
chng trnh g ri v nhng s rng buc ti nguyn. Chy chng trnh bn
trong mt mi trng gi c th s dng gim bt vn ny.

Nhng nh lp trnh h thng mt cch y th khc vi lp trnh ng dng m nhng


ngi lp trnh hng ti chuyn v mt hoc ci khc.

Trong lp trnh h thng, nhng phng tin lp trnh c hn thng sn c. S s dng


ca tp hp rc t ng th khng phi l ph bin v g ri l khng i i khi lm.
Th vin thc hin, nu sn c mi ni, th t mnh hn nhiu thng thng, v lm t
s kim tra li hn. Bi v nhng s hn ch , mn hnh v s ng k thng c
s dng; nhng h iu hnh c th c v cng chi tit ha nhng h thng con ng
k.

Thc hin nhng phn nht nh trong H iu hnh v nhng quy nh hot ng mng
nhng nh lp trnh h thng (cho v d thi hnh phn trang (b nh o) hoc mt trnh
iu khin thit b cho mt h iu hnh).

5/369
Lch s v lp trnh h thng
Trc y nhng nh lp trnh h thng khng thay i in thm ngn ng assembly.
Nhng cuc th nghim vi vic h tr phn cng nhng ngn ng bc cao vo cui
nhng nm 1960 dn dt vi nhng ngn ng nh BLISS v BCPL, tr C, gip bi
s tng ca UNIX, tr thnh l khp ni vo nhng nm 1980. C++ nhng mi y
hn nhn thy s s dng no , cho th hin trong b dng c cc trnh iu khin
Vo/ra ca Mac OS X.

6/369
Cu trc tng quan lp trnh h thng

Hnh 1-1 l biu thu gn ca h iu hnh Windows XP, n rt quan trng i vi


ngi lp trnh driver. Cc hot ng ca Windows XP u c h tr bi hai ch .
l User Mode v Kernel mode.

V d : Mt User Mode mun ti, c d liu t thit b th phi gi n chng trnh


giao tip ng dng (API) qua ReadFile.

7/369
Bi 2: CNG C LP TRNH H THNG
Cc ngn ng lp trnh
Lp trnh h thng khng nht thit phi s dng ngn ng assembly. Tht vy, tuyt
i a s cc module chc nng cu thnh h iu hnh Windows, Unix, Linux... u
c vit bng ngn ng C. u im ca cc ngn ng cp cao l r rng, d c, d
din t gii thut, din t gii thut c ng... Nh vy, nu cha tht cn thit phi
dng assembly hay ngn ng my, bn nn dng 1 ngn ng cp cao nh C, C++
vit cc ng dng ca bn.

Ngc li, ngn ng Assembly hay ngn ng my khng nht thit ch dng cho lp
trnh h thng m c th c dng vit ng dng bt k. Tuy nhin do nhc im
ca assembly v ngn ng my l qu yu din t gii thut nn rt t ngi dng
chng trc tip. Nh trn ni, ngay c khi vit h iu hnh hay cc h thng nhng
(chng trnh iu khin thit b v c ghi trn ROM ca thit b ), ngi ta cng
c gng dng ngn ng cp cao nh C, tr nhng on code c bit mi dng assembly
hay m my.

Trong trng hp buc phi dng assembly hay m my, bn phi lu rng cc
ngn ng ny ph thuc hon ton vo CPU c dng. Bn khng th vit on code
assembly hay m my m c th chy trn nhiu loi CPU c. Ring i vi CPU
Intel t 80386 tr ln, n c th hot ng 1 trong 3 ch qun l b nh khc nhau
nh: Real-mode (ch mc nh khi b reset ban u), protected-mode (qun l theo
segment) v 386-enchanced mode (qun l va theo segment, va theo page, y l ch
qun l b nh hon ho nht). Th d khi mi boot my hay khi my c boot v
chy MSDOS, CPU Intel s chy ch Real-mode, cn khi my ang chy Linux,
Windows XP... th CPU Intel chy ch 386-enchanced mode. Nu bn lp trnh
bng ngn ng cp cao, bn khng cn bit ch qun l b nh no s c dng
chy ng dng. Cn nu lp trnh bng assembly hay m my, bn cn phi nm vng
cc ch qun l b nh ca CPU, phi quyt nh ch qun l no s dng
chy ng dng, t mi bt u vit lnh tng thch vi ch qun l b nh mong
mun. Th d nu bn lp trnh ch real-mode (1 trong nhng ch 16-bit), bn
ch c th dng cc thanh ghi 16-bit ca CPU nh ax, bx, cx, dx, ds, cs, es, ss). Cn nu
bn lp trnh ch 386-enchanced mode, bn c th dng cc thanh ghi 32 bit ca
CPU, trong c 2 thanh ghi fs, gs nh bn cp. Lu rng cc ng dng vit ch
32bit ch c th chy trn mi trng Windows (hay Linux), ch khng th chy trn
MSDOS c. Chi tit v cc ch qun l b nh cng nh tp lnh CPU tng ch
qun l b nh c trnh by trong ti liu k thut gii thiu CPU tng ng. Bn
c th tm ti liu k thut trn Internet hay lin h trc tip vi cc i l ca Intel.

8/369
Gii thiu v C++
C++ l mt ngn ng lp trnh tin tin, mnh trong cc ngn ng lp trnh hin nay,
n c s dng bi hng triu lp trnh vin trn th gii. N l mt trong nhng ngn
ng ph bin vit cc ng dng my tnh v ngn ng thng dng nht lp trnh
games. c sng to bi Bjarne Stroustrup, C++ l th h sau ca ngn ng C. Thc
t, C++ gi li hu ht cc c im ca C. Nh th no i na, C++ em n cho chng
ta nhng thun li hn trong vic lp trnh.

Dng C++ cho Games:

C++ l ngn ng c cc lp trnh vin games la chn. Hu ht cc games c gii


thiu hin nay u c vit bi C++. C nhiu l do khc nhau gii thch v sao
nhng ngi lp trnh games s dng C++. y l mt vi l do:

Nhanh: Nu bn rnh C++ th bn c th lp trnh nhanh. Mt trong nhng mc tiu ca


C++ l kh nng thc thi. V nu bn cn thm cc tnh nng cho chng trnh, C++
cho php bn dng ngn ng Assembly (Hp ng) Ngn ng lp trnh bc thp nht
giao tip trc tip vi phn cng ca my tnh.

D iu khin: C++ l mt ngn ng bin ha, n h tr cc phong cch lp trnh khc


nhau, bao gm lp trnh hng i tng. Khng ging cc ngn ng khc, C++ khng
p buc lp trnh vin phi i theo mt phong cch no c.

H tr nhiu: V n l ngn ng vt tri cc ngn ng khc, c rt nhiu ti nguyn


cho ngi lp trnh bng C++, bao gm ha API v 2D, 3D, vt l, cc thit b m
thanh chnh v iu ny gip cho lp trnh vin tng tc lp trnh games.

9/369
To File thc thi: (.exe)

File m bn dng chy chng trnh d bn ang ni n game hay cc ng dng


windows gi l file thc thi (Executable File). C rt nhiu bc to mt file thc
thi t m ngun ca C++ (tp hp cc lnh trong ngn ng C++). Qu trnh ny c
m t hnh 1.1.

1. u tin, ngi lp trnh dng editor (trnh son tho) vit m ngun C++, file
thng c ui .cpp. Trnh son tho ging nh b x l ngn ng cho chng trnh, n
cho php lp trnh vin to, chnh sa, v lu tr m ngun.

2. Sau khi lp trnh vin lu li m ngun, anh (ch) ta s gi compiler (trnh bin dch)
mt ng dng c chc nng c m ngun v dch n sang file i tng (object file).
Object files thng c ui m rng l .obj.

10/369
3. Tip theo, b phn kt ni (Linker) s kt ni file object n nhng file ngoi nu cn
thit, sau to file thc thi (executable file), thng c ui m rng l .exe. n lc
ny, ngi dng c th chy chng trnh bng cch chy file thc thi.

Lu : Qu trnh ti miu t trn ch l mt trng hp n gin. to nn mt ng


dng phc tp trong C++ thng lin quan n rt nhiu file m ngun c vit bi
lp trnh vin (hay mt nhm lp trnh vin).

t ng ha qu trnh ny, lp trnh vin dng mt cng c tng hp, l IDE


(Integrated Development Environment mi trng tng thch khai trin). IDE thng
bao gm editor, compiler, linker v mt s cng c khc. Phin bn thng mi IDE cho
Windows bao gm Visual Studio.NET v C++ Builder Studio. Dev-C++ l mt ngn
ng m ngun m min ph cho Windows (hyutar: strong CD ROM km quyn sch
gc c ci Dev-C++, nhng sch ny l lu nn hng c, mi ngi c th ti ci ny
t trn net v, hoc dng C++ 6.0 hay Visual C++ cng c, mnh ngh hu ht mi
ngi u c bn thng mi ca C ri).

X l li: (error)

Khi miu t qu trnh to file thc thi t m ngun C++, ti b qua mt chi tit nh:
l li. Li l mt chuyn hay gp ca cc chng trnh my tnh. Lp trnh vin chnh
l ngi thng xuyn mc li nht. Ngay c lp trnh vin gii nht u c th mc li
ln th 1 (hoc nhiu hn) chy chng trnh. Lp trnh vin phi sa li v chy li
qu trnh to file thc thi. Sau y l mt vi loi li c bn bn thng mc phi khi
chy chng trnh:

Li bin dch (Compile Errors): N xy ra trong qu trnh bin dch. Kt qu, file object
khng c to ra. Li ny thng do li c php, c ngha l trnh bin dch khng hiu
ci g . N c th n gin nh g sai lnh chng hn, hay thiu du ;. Trnh bin
dch cn a ra nhng cnh bo (warning). Mc d bn thng khng cn phi ch
n warning, nhng bn nn gii quyt n nh l li, sa cha, sau bin dch li, y
l mt thi quen tt y ^^.

Li lin kt (Link Errors): N xy ra trong qu trnh kt ni v c th cho bit c vi th


m chng trnh lin kt n khng th tm thy. Li ny thng c gii quyt bng
cch t ng v tr cc lin kt v bt u qu trnh bin dch/kt ni ln na.

Li Run-time (Run-time errors): N xy ra khi ang chy file thc thi. Nu chng trnh
lm mt ci g khng hp l, n c th ph hy h thng. Nhng mt dng li tinh
vi, kh pht hin hn ca li run-time: logical error (li logic), c th lm chng trnh
lm nhng vic m ta khng nh trc. Nu bn tng chi game m trong nhn
vt c th bc trn khng kh (trong kch bn nhn vt khng th bc trn khng kh),
khi bn thy li logical trong hnh ng.

11/369
Trong thc t: Nh cc nh to phn mm, cng ty game thng gp rc ri vi cc sn
phm b li. Bin php khc phc ca h l trc khi em ra ngoi th trng, h thu
nhng ngi chi game th (game testers). Nhng ngi ny ch chi games, nhng
cng vic ca h khng th v nh bn tng u. H phi chi i chi li mt phn
no ca game c th ln n hng trm c gng tm xem c li no khng. V
vi cng vic bun t ny, lng ca h cng bo nho. Nhng tr thnh game testers
l mt nc thang bn c th vo lm vic ti cng ty lm games.

V d:

#include <stdio.h>

#include <conio.h>

void main()

printf(chao cac ban);

getch();

12/369
Gii thiu v Visual C++
Visual C++ l mt phn mm lp trnh hng i tng c pht trin trn c s l
ngn ng lp trnh C v C++.

Phng php thit k hng i tng va mi pht trin nhm gip nh pht trin khai
thc c sc mnh ca i tng v ngn ng lp trnh hng i tng, dng cc lp
v i tng nh l khi xy dng c s.

OOP (ngn ng lp trnh hng i tng ) l ngn ng hin thc trong chng trnh
c t chc nh tp hp nhng i tng hp tc vi nhau, mi i tng i din cho
mt instance ca mt vi lp v nhng lp m chng l thnh vin ca mt lp phn cp
thng qua quan h tha k.

1. Abstraction ( tnh tru tng) :

S tru tng th hin nhng c tnh ct yu ca mt i tng m nhng c tnh


ny dng phn bit i tng ny vi tt c cc loi i tng khc v do vy cung
cp mt cch r rng gii hn nim c ngha, lin quan n vin tng ca ngi
nhn.

Tru tng tp trung vo ci nhn b ngoi ca i tng v do tha mn c cc


hnh vi ch yu ca i tng ring bit t hin thc ca n.

Ta c th c cc loi tru tng sau:

- Thc th tru tng : mt i tng m n i din cho mt m hnh hu dng ca


mt min vn hay thc th min gii quyt.

- Operation abstraction (hot ng tru tng ) : mt i tng m n cung cp mt tp


tng qut ca cc operation, tt c cc operation thc thi cng mt loi chc nng.

- My o tru tng : mt i tng m n nhm cc hot ng vi nhau, v tt c cc


hot ng ny c s dng bi mc iu khin cao hn. Hoc cc hot ng m chng
s dng tp hp cc hot ng ca mc thp hn.

- Tru tng ngu nhin : mt i tng m n ng gi mt tp hp cc hot ng m


chng khng c quan h ln nhau.

Mt client l bt k i tng no s dng ngun ti nguyn ca i tng khc ( gi


l server). Chng ta c th biu th c im hnh vi ca i tngbng cch xem xt
nhng dch v m n cung cp cho nhng i tng khc, cng nh nhng hot ng

13/369
m n c th thc thi cho i tng khc. Quan im ny buc chng ta phi tp trung
vo ci nhn b ngoi ca i tng.

Chng ta gi ton b tp hp ca cc hot ng m mt client c th thi hnh cho mt


i tng, cng vi nhng cu lnh hp l m chng c th c gi l protocol. Mt
protocol biu th nhng cch thc m mt i tng c th hnh ng v phn ng, v
do vy c th cu thnh tng th b ngoi tnh v ng ca tru tng.

2. Encap sulation (s ng kn) :

Tnh ng kn l qu trnh phn chia cc phn t ca mt tru tng cu thnh nn


cu trc v hnh vi ca chnh n, ng kn cho php hot ng giao tip ca mt tru
tng v hin thc ca n.

S ng kn l c ch lin kt m v d liu m n thao tc, v gi cho c 2 c an


ton khi s can thip t bn ngoi v do s dng sai. Trong ngn ng hng i tng,
m v d liu lin kt vi nhau to thnh mt hp en c lp. Trong hp ny l
tt c m v data cn thit. Khi m v data lin kt vi nhau nh th mt i tng s
c to ra. Ni cch khc, i tng l mt dng c h tr cho s ng kn.

Trong mt i tng , m, data, hoc c 2 c th l private (ring) ca i tng hay


public (chung). M hoc data ring l thuc v i tng v ch c truy cp vi b
phn ca i tng. Ngha l m hoc data ring khng th truy cp bi cc phn khc
ca chng trnh tn ti ngoi i tng. Khi data l chung, cc b phn khc c th
truy cp n n mc d n c nh ngha trong mt i tng. Cc phn chung ca
mt i tng dng cung cp mt giao din c iu khin cho cc phn ring ca i
tng.

Ni chung, mt i tng l mt bin thuc kiu do ngi s dng nh ngha. Mi ln


ta nh ngha mt i tng mi, ta to ra mt loi data mi.

c bit cc thnh vin c th c t vo public, private, hay protectedca lp. Thnh


vin c khai bo l public th thy c i vi mi client, nhng thnh vin khai bo
l private th hon ton ng kn, v nhng thnh vin khai bo l protected th ch thy
vi chnh lp ca n v nhng lp con ca n. C++ cng cn cho php k hiu friend :
l lp cng hp tc c php thy nhng phn privated ca nhau.

3. Modularity (modun ha) :

Modularity l tnh cht ca mt h thng c phn tch thnh mt tp hp dnh kt


v ghp li mt cch lng lo thnh nhng modun.

14/369
Vic phn chia chng trnh thnh nhng phn ring l c th lm gim phc tp.
ngn ng ny lp, i tng hnh thnh cu trc lun l ca h thng. Chng ta t
nhng tru tng ny trong modun to ra nhng kin trc vt l ca h thng.

i vi nhng vn nh, nh pht trin c th quyt nh vn khai bo tt c cc lp


v i tng trong cng mt gi. Ta thng nhm nhng lp v i tng c quan h
trong cng mt modun, v ch phi by nhng phn t m modun khc cn thy. Trong
cc h thng ln, th n c qu nhiu modun v tht l kh cho ngi s dng tm thy
nhng lp m h cn. Hn na , khi quyt nh thay i hng trm modun phi c
hiu chnh hoc bin dch li. Nh vy, modun ha i khi cng khng tt.

Modun phc v nh l nhng phn t v nhng n v khng th phn chia c ca


phn mm m c th s dng li c qua cc ng dng. Nh pht trin s chn cch
ng gi i tng thnh cc modun sao cho chng thun tin s dng li.

4. Hierachy (h thng phn cp) :

H thng phn cp l mt s sp xp theo th bc hay sp t cc tru tng. C hai


phn cp quan trng nht trong mt h thng phc tp l : cu trc lp ca n(phn cp
is a), v cu trc i tng ca n ( phn cp part of ).

Tha k n gin: tha k l mi quan h is a . tha k nh ngha mt mi quan h


gia cc lp, trong mt lp chia s cu trc v hnh vi c nh ngha trong mt
lp hay nhiu lp ( tng ng vi tha k n gin v a tha k ). Do tha k nh
l s phn cp ca cc tru tng, trong mt lp con tha k mt hay nhiu lp cha.

a tha k a n mt s vn phc tp cho ngn ng lp trnh. Nhng ngn ng


phi a ra hai vn : xung t gia tn ca cc lp cha khc nhau, v tha k c
lp li nhiu ln. S xung t xy ra khi hai hay nhiu lp cha cng cp cng chia s
mt lp cha chung. V trong trng hp nh vy, lp l c mt hoc nhiu bn sao cu
trc ca lp cha c dng chung . Mt s ngn ng th khng cho php tha k lp
li, mt s khc th chn hng khc. C++ cho php ngi lp trnh quyt nh: virtual
base class (lp c s o ) c dng ch ra s dng chung ca cu trc lp li, trong
khi nonvirtual base class c kt qu l trng bn sao lp con.

5. Kim tra kiu ( typing ) :

Typing l s tun theo bt buc ca lp i tng, nh l nhng i tng ca cc lp


khc nhau khng c thay th ln nhau hoc chng c th thay th ln nhau ch theo
mt cch thc rt hn ch.

C++ c khuynh hng kim tra kiu cht ch nhng ta c th l i hay cm kim
tra.Tnh a dng (polymorphism):

15/369
L tnh cht cho php mt tn c dng cho hai hoc nhiu mc ch khc nhau c
quan h v phng din k thut. Mc ch ca tnh a dng khi c p dng cho OOP
l cho php mt tn c dng ch r mt lp tc ng tng qut, mt tc ng c
th c xc nh bi loi data. V d, trong C, khng c h tr tnh a dng nn mt
tc ng gi tr tuyt i cn phi c ba hm khc nhau: abs(), labs(), v fabs(). Cc hm
ny tnh ton v ln lt tr v mt gi tr tuyt i ca s nguyn, mt s nguyn di,
mt gi tr du phy ng. Tuy nhin, trong C++ c c tnh a dng nn c hm abs().
Loi data c dng gi hm xc nh loi hm no thc s c dng. Trong C++
c th s dng mt tn hm cho nhiu mc ch khc nhau. iu ny c gi l qu ti
hm(function overloading).

Tng quan hn khi nim tnh a dng l tng mt giao din, nhiu phng php.
iu ny c ngha l c th thit k mt giao din chung cho mt nhm cc tc ng c
lin quan. Tuy nhin, tc ng c th c thi hnh ph thuc vo data. u im ca
tnh a dng l chng lm gim tnh phc tp bng cch cho php cng mt giao din
c s dng ghi r mt lp tc ng tng qut, chnh trnh bin dch s la chn
tc ng c th khi p dng cho tng trng hp. L ngi lp trnh ta khng phi thc
hin s la chn ny bng tay. Ta ch cn nh v s dng giao din chung.

Lin kt tnh v kin kt ng (Static and Dynamic Binding):

Khi nim trong typing v static typing lin kt tnh l hon ton khc nhau. Strong
typing cp ti s nht qun ca kiu. Stactic binding c ngha l kiu ca mi bin
v biu thc l c nh vo lc bin dch. Dynamic binding ngha l cc kiu ca mi
bin v biu thc khng cho bit cho ti khi chy chng trnh. Bi v Strong typing
v Dynamic binding l khi nim c lp cho nn mt ngn ng c th va Strong v
Static typing.

6. Bn cht ca i tng:

Mt i tng c trng thi, hnh vi, c tnh nhn dng; cu trc v hnh vi ca cc i
tng ging nhau c nh ngha trong mt lp chung ca chng, thut ng instance
v i tng l c th thay th ln nhau c.

Trng thi (state) : ca mt i tng bao gm tt c cc c tnh (thng l tnh) ca


i tng tr i gi tr hin ti ( thng l ng ) ca mi c tnh .

Hnh vi (behavior ) : l i tng hot ng v phn ng nh th no theo iu kin


trng thi ca n thay i v message truyn n.

Operations (hot ng) : l mt dch v m mt lp cung cp cho khch hng ca n.


Chng ta thy rng mt client thng thc thi nm loi opearation i tng. Ba loi
operation thng thng nht l :

16/369
Modifier : l operation thay i trng thi ca i tng. Selector: l Operation truy
xut trng thi ca i tng nhng khng lm thay i trng thi ca n.

Iterrator : l operation cho php tt c cc phn ca mt i tng c truy xut theo


mt th t nh ngha trc. Hai loi operation thng dng khc cn thit to v
hy nhng instance ca mt lp l :

Constructor: l operation to i tng v (hoc) khi ng trng thi ca n.

Destructor l operation gii phng trng thi ca mt i tng v (hoc) hy chnh


i tng .

Indentify: (c im nhn dng) : indentify l c tnh ca mt i tng phn bit


n vi cc i tng khc.

7. Mi quan h gia cc i tng:

Links( lin kt) : Link l ni kt vt l hay nim gia cc i tng. Mt i tng


cng tc vi mt i tng khc thng qua link ca n ti nhng i tng ny. Hay
ni cch khc, mt link v ngha l mt hp tc c th qua mt i tng ( client) p
dng nhng dch v ca i tng khc (nh cung cp) hoc qua mt i tng c
th iu khin i tng khc. Mt i tng c th ng cc vai tr sau:

Actor : mt i tng c th lm vic trn mt i tng khc nhng n khng bao


gi cho mt i tng khc lm vic trn n, thut ng actor v active object c th thay
th ln nhau.

Server: mt i tng khng bao gi lm vic trn mt i tng khc, n ch cho i


tng khc lm vic trn n.

Agent : mt i tng va lm vic trn i tng khc va cho i tng khc lm


vic trn n, mt i l thng c to ra lm cng vic cho mt actor hay mt
agent khc .

i tng c cung cp l global i vi client.

i tng cung cp l mt tham s cho cc operation ca client.

i tng cung cp l mt phn ca i tng client.

i tng cung cp c khai bo cc b trong operation ca client.

17/369
Khi c multiple thread control, vic truyn thng tin gia cc i tng cn x l vn
multual exclusion trong h thng x l ng thi. Vn ng b ha cng phi xem
xt.

Aggregation: Aggregation c ngha l mt phn cp tng th / b phn, vi kh nng


iu khin t tng th ( cn gi l aggregate ) ti nhng b phn (c hiu l nhng
thuc tnh ca n).

8. Bn cht ca lp:

Class (lp) : l tp hp ca cc i tng c cng cu trc chung hay hnh vi chung.


Mt i tng n gin ch l mt instance ca lp.

Interface: ca mt lp cho thy bn ngoi ca i tng v do nhn mnh n vn


tru tng trong khi che du cu trc v hnh vi bn trong.

Implemention : ca mt lp l ci nhn bn trong ca n. Implemention ca mt lp


c bn bao gm tt c cc operation c nh ngha trong interface. Chng ta chia
interface ca lp thnh ba phn:

Public : l khai bo c truy xut n mi client.

Protected : l khai bo c truy xut ch chnh lp , lp con ca n, v lp friend.

Private: l khai bo c truy xut ch chnh lp v lp friend.

9. Mi quan h gia cc lp:

Phn ln ngn ng hng i tng h tr trc tip mt vi kt hp ca nhng quan h


sau y:

Association : gm c quan h mt-mt, mt-nhiu, nhiu-nhiu.

Inheritance (tha k) : l mt lp chia s cu trc v (hoc) hnh vi c nh ngha


bi mt lp (n tha k) hoc nhiu lp (a tha k).

Aggregation (kt tp) : quan h kt tp gia cc lp ging nh quan h kt tp gia cc


i tng tng gia cc lp . a tha k thng b ln ln vi kt tp. Trong C++
tha k protected hay private d dng b thay th bi kt tp protected hay private ca
instace ca lp cha, m khng mt tnh ng ngha ca n.

V d:

18/369
#include "stdafx.h"

#include "conio.h"

#include "stdio.h"

int main(int argc, char* argv[])

printf("chao");

getch();

return 0;

19/369
Bi 3: THC HNH MT S BI TP
C BN TRN C++
Thc hnh mt s bi tp c bn trn C++
Bi 1

Vit cu trc, cc kiu d liu, cc cu trciu kin, cu trc lp trong C ++

Bi 2

Vit chng trnh gii phng trnh bc 2 trn C++

20/369
Bi 4: C BN V CU TRC V
DRIVER
Tm lc lch s cc b iu khin thit b
Nhng th h PC u tin chy trn mt chip x l Intel cung cp kh nng
nh v cho 640KB ca b nh thc tgi nh vy bi v b nh l tht s
trong mu ca nhng chip nh m b x l trc tip hng vo bi nhng phng tin
ca mt a ch vt l 20 bit. Chnh b x l ngh cho ci ng kiu ca qu trnh
hot ng, ci gi l kiu thc t, ch no b x l kt hp thng tin t hai thanh
nghi 16-bit hnh thnh mt a ch b nh 20-bit cho mi ch dn b nh nhc n
. Kin trc my tnh bao gm khi nim ca nhng khe m rng m mt vng c th
nhng ngi dng bt chp vi nhng card mua ring r t bn thn my tnh. Nhng
card t chng thng xuyn n vi nhng ch th v lm sao t nhng cng tc
DIP (tr, cc jumper gia cc pin) th t to ra nhng thay i khng ng k cu
hnh Vo/ra. Bn phi gi mt s ca tt c s Vo/ra v nhng s n nh ngt cho
PC ca bn th t cho s ph hp ny. MS-DOS hp nht mt lc c s trn file
CONFIG.SYS nh h iu hnh h thng c th np vo nhng b iu khin thit
b kiu ch thc cho thit b nguyn bn v cho cc card thm vo. Chc chn, y
l nhng trnh iu khin theo hnh thc lp trnh ngn ng assembly v tin vo mt
phm vi ln hn hoc km hn trn ch th INT gi ti BIOS v ti nhng phc v h
thng bn trong bn thn MS-DOS. Nhng ngi dng kt thc bt buc hc lm sao
cu khn nhng ng dng qua cc lnh. Cc phn mm ng dng cn thit hc lm
sao lp trnh hin th video, bn phm, v con chut ngay lp tc bi v khng mt
MS-DOS no m BIOS h thng lm y nh vy.

Sau ny, IBM c gii thiu dng AT ca nhng my tnh c nhn t c s trn h vi
x l Intel 80286. B x l 286 thm mt kiu bo v ca thao tc ch nhng chng
trnh c th hng vo ln trn ti 16 MB ca b nh m rng v b nh chnh s dng
a ch on 24-bit (theo danh ngha gin tip qua mt b chn lc on mt thanh ghi
on 16-bit) v mt a ch offset 16-bit. Bn thn MS-DOS vn l mt H iu hnh
h thng ch thc, nh vy vi nh cung cp phn mm xy dng cc sn phm m
rng DOS ti cho php nhng ngi lp trnh di tr nhng ng dng kiu thc t ca
h ti kiu bo v v chp nhn li ch to tt c b nh m ang tr nn sn c trn th
trng. T MS-DOS ng yn v tr u ca my tnh, cng ngh iu khin
khng pht trin thi im ny.

S thay i bc ngot ca cng ngh PC xut hintrong tng quan ca ti, d sao i
nakhi m Intel a ra bn chip x l 80386. Dng 386 cho php nhng chng trnh
truy nhp ln trn ti 4 GB ca a ch b nh o gin tip qua cc bng trang nh, v

21/369
n cho php nhng chng trnh d dng s dng nhng s lng cho 32-bit s
hc v a ch. l mt cn gi mnh ca s hot ng trong th trng nhng cng
c phn mm nh nhng nh cung cp chng trnh bin dch v s cnh tranh gia cc
cng ty a ra bt khi lng tng trng lin tc khao kht nhng ng dng ln
hn cho tc x l v tc b nh. Nhng trnh iu khin thit b l vn cn vit ra
nhng chng trnh ch thc 16-bit trong ngn ng assembly v ci t qua tp
CONFIG.SYS, v nhng ngi dng cui vn cn cn cc card c nh cu hnh
iu khin bng tay.

K tip tin ti cc chip ca B vi x l ch yu trong vng ca s thc thi v dung


lng. Trong khi ti vit chng ny, nhng my tnh hot ng nhanh hn 1 GHz vi
nhng cng 50-GB v 512 MB (hoc hn) ca b nh l c rch v c th cung cp d
dng bng nhng phn on ln hn ca mu.

Song song vi s tin ha ca nn tng cng ngh my tnh, s tin ha khc ang xut
hin vi cng ngh h iu hnh. Hu ht mi ngi, thm ch bao gm nhng ngi
lp trnh ca phn mm h thng, thch nhng bin php trn nn ha ca nh hng
ln nhau vi cc my tnh ti nhng bin php trn nn vn bn. Microsoft mun ti
nhm H iu hnh haApple nh trng vi h Macintosh u tinnhng c
n v thng tr n vi gia nh Windows ca nhng H iu hnh. Trong s bt u,
Windows ch l mt tin ch ha cho MS-DOS kiu thc t. Trong c thi gian, mt
tp hp ca cc trnh iu khin Windows cho phn cng ph bin, k c mn hnh ,
bn phm, v chut, cho n s tn ti. Nhng b iu khin ny l nhng tp tin c th
thc hin vi mt ui m rng .DRV, v chng c vit u tin trong ngn ng
assembly.

n vi lp AT ca my tnh, Microsoft thit lp mt phin bn ch bo v ca


Windows. Microsoft mang chuyn cc trnh iu khin .DRV ch thc ch bo
v l tt nht. Phn cng khc hn nhng thit b Windows chun (mn hnh, bn phm,
v con chut) tip tc s c iu khin bng cc trnh iu khin MS-DOS ch
thc.

Kt lun li, mt khong thi gian sau cc PC vi cc b x l 386 tr nn sn


dng mi ni, Microsoft pht hnh Windows 3.0, ca ch tng cng cc thao
tc bt ly y s thun li ca cc kh nng b nh o. Thm ch nh vy, n vn
cn ng vi mi b phn mi ca nhu cu phn cng mt iu khin ch thc.
Nhng by gi n l mt vn ln. T mt s h tr a nhim ca cc ng dng MS-
DOS (mt nhu cu chp nhn cho ngi s dng cui ca Windows), Microsoft l
xy dng mt h iu hnh cho my o. Mi ng dng MS-DOS chy trong my o ca
chnh mnh, nh lm mi trng ha cho Windows. Nhng tt c cc ng dng
MS-DOS trc tip ang c gng ni ti phn cng bng s a ra cc cu trc IN v
OUT, b nh thit b c v ghi, v vic dng cc ngt t phn cng. Hn na, hai hoc
nhiu hn cc ng dng ang chia s thi gian x l c th ang a ra nhng ch dn

22/369
xung t ti phn cng. Chng chc chn xung t qua s s dng ca mn hnh, bn
phm, v con chut, ca qu trnh din bin.

Ti vic chp nhn cc ng dng phc tp ti vic chia s phn cng vt l, Microsoft
gii thiu khi nim ca mt b iu khin thit b o, mc ch rng ca ai ti thc
t mt thit b phn cng. Nhng b iu khin nh vy l khi qut gi l VxDs bi v
hu ht chng cho php nhng tn file ph hp vi nhng mu VxD.386, u ch
bo kiu ca thit b qun l chng. S dng khi nim ny, Windows 3.0 to s
xut hin ca trang b nhng c my o vi nhng th hin ring bit ca mt vi thit
b phn cng. Nhng t mnh nhng thit b tip tc, trong hu ht cc trng hp, ti
vic iu khin bng b iu khin MS-DOS ch thc. Mt vai tr ca VxD s iu
nh s truy cp ti phn cng bng vic chn ng u tin nhng s c gng ca cc
ng dng ti chi tit nh phn cng v kha chuyn i ngn gn B x l ti mt sp
xp ca ch thc gi cho ch 8086 o ti vic chy trnh iu khin MS-DOS.

khng t mt mt qu tinh t trn n, kha chuyn i ch chy nhng b


iu khin kiu thc t l mt s tn cng cng dng duy nht ca chng l chp nhn
n cho mt s tng tri chy hp l trong nn phn cng v h iu hnh. Windows
3.0 c mt vi hng hc tnh nng gc nguyn nhn l ci rt c trng ca cu
trc. Microsoft tr li l ti OS/2, khi n l ang pht trin s cn i ( l s
dng th k 20) vi IBM.

Microsoft c phin bn ca OS/2 tr thnh l Windows NT, phin bn dng chung u


tin ca chng l vo nhng nm 1990, khng lu sau Windows 3.1. Microsoft xy dng
Windows NT t trn nn vi nh ca vic to n mt cch lu bn v nn tng bo
m trn vic chy nhng h iu hnh. Nhng trnh iu khin cho Windows NT
s dng mt cng ngh nhn-kiu mi toanh l khng c chia s trn thc t vi
hai b cng ngh iu khin khc khi y ang c thnh hnh. Nhng trnh iu khin
Windows NT s dng gn nh ch ring ngn ng lp trnh C v vy chng c th
c bin dch li cho nhng cu trc CPU mi m khng yu cu bt k nhng s thay
i ngun no.

Vn khc xy ra dc theo khung thi gian v Windows 3.0 c mt s phn


nhnh quan trng cho chng ta hm nay. Windows 3.0 chnh thc b tch ra khi th gii
phn mm vo trong cc chng trnh User-mode v Kernel-mode. Nhng chng trnh
User-mode bao gm tt c cc chng trnh ng dng v cc tr chi mi ngi
mua cc my tnh chy, nhng chng l khng c lng tin giao du mnh (hoc
thm ch trung thc) vi phn cng hoc vi cc chng trnh khc. Nhng chng
trnh Kernel-mode k c chnh H iu hnh v tt c cc trnh iu khin thit b m
mi ngi thch bn v ti vit. Nhng chng trnh Kernel-mode l c th tin cn
c hon ton v c th chm bt k ti nguyn h thng no m chng thch. Mc d
vy Windows 3.0 tch ring cc chng trnh bng kiu ca h ca H iu hnh, khng
phin bn no ca Windows (khng ch l Window Me) tht s t s bo v b nh

23/369
trong ch nhng b mt h thng bo mt. Bo mt l mt lnh vc ca Windows
NT v nhng ngi k nghip n, m ngn cm cc chng trinhg user-mode t vic
nhn thy hoc thay i nhng ti nguyn qun l bi nhn.

Ngun my tnh l khng tht s tin b ti im ni m mt PC trung bnh c th


chy Windows NT tt cho n khi mi y c a chung. Microsoft v th phi gi
cho dng sn phm Windows hot ng. Windows 3.0 pht trin thnh 3.1, 3.11, v 95.
ang bt u vi Windows 95, nu bn mun vit mt trnh iu khin thit b, bn vit
ci g gi mt VxD ci tht s l mt b iu khin bo v ch 32-bit. Cng
bt u vi Windows 95, nhng ngi dng cui cng c th nm ra khi nhng s
Vo/ra ca h bi v tnh nng Plug v Play mi ca nhn bit h iu hnh h thng v
c phn t ng cu hnh phn cng. Nh mt nh sn xut phn cng, tuy nhin bn c
th phi vit mt trnh iu khin real-mode gi nhng vui lng ca cc khch hng
ca bn m ai khng phi nng cp t Windows 3.1. trong lc , Windows NT pht
trin thnh 3.5, 4.0. Bn cn mt b iu khin th ba h tr nhng h thng ny,
v khng phi bit nhiu kin thc lp trnh ca bn c th chuyn gia nhng d n.

Microsoft thit k mt cng ngh mi cho cc trnh iu khin thit b, ch


iu khin Windows (WDM), v a vo Windows 98 v Windows Me, nhng ngi
ni nghip ti Windows 95. H cng a nhng cng ngh ny ti Windows 2000
v Windows XP, nhng ngi ni nghip ti Windows NT 4.0. Bng thi gian ca
Windows Me, MS-DOS hin hu ch do s gip v l s khng cn thit cui
cng cho mt nh sn xut phn cng lo lng v nhng b iu khin thit b real-
mode. V WDM, t nht bi mc ch ban u, thc t l cng nh th v tt c cc nn
tng, n tr nn c th thc hin c vit ng cho mt b iu khin.

Tng kt, chng ta hm nay ng hnh bng ca kin trc PC nguyn bn v ca


nhng phin bn u tin ca MS-DOS. Nhng ngi dng cui vn cn thnh thong
phi m lp v ca cc PC khc ci t cc card m rng, nhng chng ta s dng
mt bus mnh hn v khc ngy nay hn chng ta lm trc y. Plug v Play v bus
PCI phn ln loi b nhu cu cho nhng ngi dng cui gi li rnh ghi ca Vo/
ra, b nh, v cch s dng yu cu dng ngt. Vn cn c mt BIOS ng ch, tr phi
ngy nay cng vic ca n phn ln khi ng h thng v khai bo h iu hnh
thc t (Windows XP hoc Windows Me) khong cu hnh nhng chi tit pht hin ra
dc theo ng i. V nhng trnh iu khin WDM vn cn c tp c phn m rng
.SYS, ng nh nhng b iu khin real-mode u tin lm.

24/369
Tng quan v cc H iu hnh (An Overview of the
Operating Systems)
Windows Driver Model cung cp mt khung cho cc b iu khin thit b hot ng
2 h iu hnh h thngWindows 98/Windows Me v Windows 2000/Windows
XP. Nh c tho lun v trong tm lc lch s trc y, hai cp ny ca nhng h
iu hnh l cc sn phm ca hai con ng ca s pht trin song song. Tht ra, ti
s tham chiu ti cp trc kia ca nhng h thng vi s tm tt Windows 98/Me
nhn mnh di sn chung ca h v and to ci ghp i n gin nh XP. Mc
d ti ngi dng cui hai cp ny ca nhng h thng l ging nhau, chng lm vic
kh khc nhau trong. on ny, Ti s gii thiu tng quan v ngn gn ca hai h
thng ny.

Tng qua v Windows XP

Hnh 1-1 l mt tm tt cao s chc nng ca h iu hnh Windows XP, kha cnh
no ti nhn mnh nhng c trng m quan trng ti nhng ngi m vit nhng
b iu khin thit b. Mi nn tng m Windows XP chy h tr hai kiu ca s thi
hnh. Phn mm thc hin hay trong user-mode hoc trong kernel-mode. Mt chng
trnh user-mode iu mun ti, ni, c d liu no t mt thit b gi l mt giao
din lp trnh ng dng (API) nh ReadFile. Mt module h thng con nh nhng s

25/369
thi hnh KERNEL32.DLL API ny bng vic ko theo mt chc nng API bn ng nh
NtReadFile. cp ti kha cnh c thm thng tin v API bn ng.

Chng ti thng ni NtReadFile c gi l qun l Vo/ra. Thut ng qun l Vo/ra


l c th mt t lc ng bi v khng l bt k m un c th thc hin n no
vi tn . H iu hnh s giao tip vi thit b bng trnh iu khin ca ring mnh.

Nhiu th tc phc v nh NtReadFile. H vn hnh kernel-mode th t phc v


mt vi ng dng tng tc vi mt thit b trong cch no .

API gc

NtReadFile thuc API ca Windows XP. H iu hnh Windows NT bao gm mt s


h thng thc thi nhng ng ngha ca vi ci mi v nhng h iu hnh ang tn
ti. c mt h thng con OS/2, POSIX, v h thng con Win32. Nhng h thng con
c thc hin bng vic to m user-mode hng ti API gc, m chnh n c thc
hin trong kernel-mode.

Mt user-mode DLL c tn (rather redundantly, Ive always thought) NTDLL.DLL


nhng b sung API gc cho nhng i tng gi Win32. Mi mc vo trong DLL ny
l mt trnh bao bc mng xung quanh mt s gi ti mt chc nng kernel-mode maf
tht s thc hin chc nng. Vic gi s dng mt giao din cng tc h thng ph thuc
nn chuyn iu khin ngang qua ranh gii user-mode/kernel-mode. Trn nhng b
x l Intel mi hn, giao din cng tc h thng ny s dng ch dn SYSENTER. Trn
nhng b x l Intel c hn, nhng s s dng giao din cu trc INT vi vi chc nng
vit m 0 x2E. Trn nhng b x l khc, vn cn nhng c ch khc c s dng.
Mc d, bn v ti khng cn hiu nhng chi tit ca c ch vit nhng b iu khin
thit b. Tt c chng ti cn hiu l c ch cho php mt chng trnh c chy trong
user mode gi mt chng trnh con m thc hin kernel mode v nh dn dn
tr li ngi gi user-mode ca n. Khng c s chuyn mch ng cnh lung xut hin
trong thi gian x l: tt c nhng s thay i l mc c quyn ca thc hin m (cng
vi vi chi tit khc nhng lp trnh vin hp ng duy nht tng ch hoc quan tm
xung quanh).

H thng Win32 l mt trong a s nhng lp trnh vin ng dng quen thuc vi v n


thi hnh nhng chc nng mt trong nhng s kt hp ph bin vi h giao din ho
Windows.

Mt b iu khin thit b c th dn dn cn truy nhp tht s phn cng ca n


thc hin mt IRP. Trong nhng trng hp ca mt IRP_MJ_READ ti mt loi vo/
ra (PIO) c chng trnh ha ca thit b, s truy nhp c l a mu (dng) (ca)
mt thao tc c c nh hng i mt cng vo/ra hoc mt thanh ghi b nh c
ng k bng thit b. Nhng b phn iu khin, mc d h thc hin trong kernel-

26/369
mode v c th bi vy ni trc tip ti phn cng ca h, s dng nhng phng tin
c cung cp bi lp tru tng ha phn cng (HAL) truy nhp phn cng. Mt
thao tc c c l bao gm s gi EAD_PORT_UCHAR c mt byte d liu t
mt cng Vo/ra. HAL thng s dng mt phng php platform-dependent tht s
thc hin thao tc HAL thng l s dng mt phng php ph thuc nn tng tht
s thc hin thao tc. Trn mt my tnh x86, HAL s dng trong lnh IN; trong mt
nn tng Windows XP tng lai khc no , n c l thc hin mt cng vic np
vo b nh.

Sau khi mt trnh iu khin kt thc vi mt thao tc Vo/ra, n hon thnh IRP
bng vic gi mt th tc dch v kernel-mode c bit. Hon thnh l mn cui cng
trong vic x l mt IRP, v n cho php ng dng ch i thc hin li.

27/369
Cc kiu Driver
Mt s loi ca mu cc trnh iu khin mt h thng XP Windows y . Hnh 1-4
nhng s ring bit ca chng.

Hnh 1-4. Cc kiu ca cc trnh iu khin thit b trong Windows XP.

Mt trnh iu khin thit b o(VDD) l mt thnh phn user-mode iu


cho php cc ng dng MS-DOS-based truy cp phn cng trn cc nn tng
Intel x86. Mt VDD tin vo mt n cho php trn vo/ra by s truy nhp
cng, v n thc cht m phng thao tc ca phn cng cho li ch ca cc ng
dng iu trc tip trc y c chng trnh ha ni ti phn cng
trn mt my ti thiu. ng nhm ln mt Windows XP VDD vi mt
Windows 98/Me VxD. C hai c gi l nhng b iu khin thit b thc t,
v h phc v cng mc ch c bn phn cng thc t, nhng h thu cng
ngh phn mm hon ton khc nhau.
Nhng loi trnh iu khin thit b kernel-mode bao gm mt s loi con. Mt
trnh iu khin PnP l mt trnh iu khin kernel-mode m hiu cc giao thc
Plug and Play ca Windows XP. hon ton chnh xc, sch ny lin quan
nhng trnh iu khin PnP v khng c g khc.
Mt trnh iu khin WDM l mt trnh iu khin PnP m ng thi hiu cc
giao thc power-management v l ngun thch hp vi c Windows 98/Me v
Windows 2000/XP. Bn trong phm tr ca trnh iu khin WDM, bn c th
cng phn bit gia lp nhng trnh iu khin (m qun l mt thit b thuc
v lp c nh ngha k no ca thit b) v nhng trnh iu khin nh
(tr gip vendor-specific v nh cung cp ti mt lp b phn iu khin), v
gia nhng trnh iu khin chc nng nguyn khi (m gm mi th chc
nng cn h tr mt thit b phn cng) v lc nhng trnh iu khin (Nhng
thao tc vo/ra lc no cho mt thit b c bit trong th t thm hay sa
i hnh vi).

28/369
Nhng trnh iu khin tp tin h thng thc thi mu tp tin h thng PC chun
(m bao gm nhng khi nim ca mt cu trc th mc phn cp vic cha
t tn nhng tp tin) trn nhng a cng a phng hay qua nhng kt ni
mng. y cng, l nhng trnh iu khin kernel-mode.
Nhng b iu khin thit b k tha l cc trnh iu khin kernel-mode m
trc tip kim sot mt thit b phn cng khng c tr gip t nhng trnh
iu khin khc. Phm tr ny thc cht bao gm nhng trnh iu khin cho
nhng phin bn trc ca Windows NT m ang chy khng c s thay
i trong Windows XP.

C mt s thit b, bn khng cn vit bt k trnh iu khin no bi v Microsoft


cung cp mt trnh iu khin chung m s lm vic vi thit b ca bn. y l mt vi
v d:

Thit b tn tr tin ln SCSI-compatible hoc ATAPI-compatible


Bt k thit b no ni ti mt cng USB m hon ton thch hp vi mt
thuyt minh ph chun, cung cp bn hnh phc vi bt k hn ch no
trong trnh iu khin Microsoft tiu chun
Cng tun t chun hay cng chut PS/2
Bn phm chun
Card iu hp video khng c gia tc hay nhng tnh nng c bit
Cng song song hay tun t chun
a mm chun

WDM Drivers

Cho a s nhng thit b m Microsoft khng trc tip s h tr, bn cn vit mt trnh
iu khin WDM. Bn s vit mt trnh iu khin chc nng nguyn khi, mt trnh
iu khin lc, hay n gin l mt trnh iu khin nh.

WDM minidrivers

Nu Microsoft vit mt trnh iu khin cho thit b, bn c gng cho thit b h


tr, bn cn phi vit mt Minidriver lm vic vi trnh iu khin lp . Minidriver
ca bn trn danh ngha trong vic ph trch ca, tr phi bn s gi nhng chng trnh
con trong trnh iu khin lp m v c bn ly li qun l ca phn cng v gi quay
tr li bn lm nhng th device-dependent khc nhau. S lng ca cng vic bn
cn lm mt minidriver thay i gh gm t mt lp ca thit b n thit b khc.

y l mt s v d ca nhng lp thit b m bn cn phi lp k hoch vit mt


minidriver:

29/369
Cc HID Non-USB, bao gm chut, cc bn phm, cc cn iu khin, nhng
bnh li, vn vn. Nu bn c mt thit b USB (cho) hnh vi chung no ca
HIDUSB.SYS (nhng trnh iu khin Microsoft cho nhng thit b USB HID
cn thiu, bn cng nn vit mt minidriver HIDCLASS minidriver. Phn ch
yu in hnh ca nhng thit b ny l h bo co ngi s dng c nhp
vo bng phng php nhng bo co m c th c m t bi mt cu trc
d liu b m t. Cho nhng thit b nh vy, phc v HIDCLASS.SYS nh
trnh iu khin lp v thc hin nhiu chc nng iu Direct-Input v
nhng lp bc cao khc ca phn mm tip tc ph thuc, v th l bnre
tng i b kt nhiu vi vic s dng IDCLASS.SYS. y kh khn
ti dnh cho khng gian ng k tn tm ti n sau trong sch ny. Nh mt
s ni ring, HIDUSB.SYS chnh n l mt HIDCLASS minidriver.
Nhng thit b Windows Image Acquisition (WIA), bao gm nhng scanner v
nhng camera. Bn s vit mt WIA minidriver m thc cht thc hin mt vi
mch ghp ni COM-style ti nhng din mo h tr vendor-specific ca phn
cng ca bn.
Nhng thit b Lung, nh m thanh, DVD, v nhng thit b video, v nhng
b lc software-only cho nhng dng d liu a phng tin. Bn s vit mt
dng minidriver.
Nhng thit b giao din Mng trn nhng bus khng truyn thng, nh USB
hay 1394. Cho mt thit b nh vy, bn s vit mt mt trnh iu khin
miniport Network Driver Interface Specification (NDIS) vi mt kha cnh
thp hn WDM, ti s dng nhng cm t ging nh ti liu DDK trn ch
ny. Mt trnh iu khin nh vy khng chtrinhflinh ng gia nhng h
iu hnh, v th l bn cn phi lp k hoch trn s ghi ring bit ca h vi
nhng s khc nhau nh hn i ph vi nhng phn ph thuc nn tng.
Nhng card Video. Nhng thit b ny yu cu mt video minidriver m lm
vic vi b iu khin lp cng video.
Nhng my in, m i hi thay cho cc DLL user-mode ca cc trnh iu
khin kernel-mode.
Nhng ngun pin, Microsoft cung cp mt trnh iu khin lp chung. Bn vit
mt minidriver (DDK no gi l mt trnh iu khin miniclass, nhng cng
th ca n) lm vic vi BATTC.SYS.

Nhng trnh iu khin lc WDM

Mt thit b vn hnh sao cho gn ti mt tiu chun c tha nhn mt trnh iu


khin Microsoft chung gn nh thch hp. Trong mt s hon cnh, bn c th c
kh nng vit mt trnh iu khin lc m sa i hnh vi ca trnh iu khin chung
phi lm cng vic phn cng ca bn. iu ny xy ra rt thng xuyn, nhn tin,
v thng ca n khng phi d dng thay i cch m mt trnh iu khin chung
truy nhp phn cng.

30/369
Nhng trnh iu khin chc nng WDM nguyn bn

Vi mt s ngoi l s c ghi chp trong mc tip theo, a s nhng kiu khc (ca)
thit b yu cu ci g Ti c gi cho y mt trnh iu khin chc nng WDM nguyn
khi. Mt trnh iu khin nh vy thc cht ng mt mnh v x l tt c cc chi tit
ca kim sot phn cng ca bn.

Khi kiu ny ca trnh iu khin thch hp, Ti khuyn co cch tip cn sau y v th
m bn c th kt lun vi mt bit nh phn l s lm vic vic trn cc nn tng Intel
x86 trong tt c cc h iu hnh. u tin, xy dng vi nhiu DDK gn y nht
Ti s dng mt phin bn beta ca DDK .NET cho nhng v d tiu biu trong ni dung
sch hng dn. Bn c th s dng IoIsWdmVersionAvailableto quyt nh h iu
hnh no m bn tnh c ang s dng. Nu bn tnh c c chy trong Windows 2000
hay Windows XP, bn c th gi l MmGetSystemRoutineAddress c mt con tr ti
mt chc nng Windows XP-only. Ti cng gi mt hi cng WDMSTUB.SYS, m
c bn lun trong Ph lc A, nh ngha MmGetSystemRoutineAddress v nhng
hm nhn then cht khc trong Windows 98/Me; cch khc, trnh iu khin ca cc
bn n gin khng ti c trong Windows 98/Me bi v nhng nhp khu khng xc
nh.

y l mt s v d ca nhng thit b m cho bn c l vit mt chc nng trnh


iu khin WDM nguyn khi:

Bt c loi SmartCard loi ra ngoi tr mt loi c gn cho mt cng tun t


B bin i Digital-to-analog
Card ISA h tr quyn xc minh s hu th c/ghi b chuyn i

Nhng kiu ca cc trnh iu khin khc

Vi v tr tn ti trong mt trnh iu khin chc nng WDM nguyn khi khng


chin thng bi v nhng s khc nhau kin trc gia Windows 98/ Me v Windows
2000/ XP. Trong nhng trng hp sau y, bn cn vit hai trnh iu khin: mt trnh
iu khin WDM cho Windows 2000/XPv mt trnh iu khin VxD cho Windows 98/
Me:

Mt trnh iu khin cho mt cng ni tip. Trnh iu khin trn Windows 98/
Me l mt VxD m a ra giao din trnh iu khin cng VCOMM ti cnh
trn ca n, trong khi m trnh iu khin Windows 2000/ XP l mt trnh iu
khin WDM l nhng xut rt hay v nghim khc ch r giao din
IOCTL ti mp trn ca n. Hai thuyt minh upper-edge khng c ci g chung.
Mt trnh iu khin cho mt thit b ni ti mt cng ni tip. Trnh iu
khin Windows 98/Me l mt VxD m gi l VCOMM ni chuyn vi
cng. Trnh iu khin Windows 2000/XP l mt trnh iu khin WDM m

31/369
ni chuyn vi SERIAL.SYS hay mt vi trnh iu khin cng ni tip khc
m thc hin cng giao din IOCTL.
Mt trnh iu khin cho mt thit b tr tin ln USB khng tiu chun. Dnh
cho Windows 98/Me, bn s vit mt VxD m iu chnh vo trong s phn
cp gim st vin Vo/ra ca nhng trnh iu khin phn tng. Dnh cho
Windows 2000/XP, bn s vit mt trnh iu khin chc nng WDM nguyn
khi l cc khi yu cu SCSI chp nhn cnh trn ca n v giao tip vi
thit b USB ti mp thp hn ca n.

Dnh cho hai lp ca thit b, Microsoft nh ngha mt kin trc trnh iu khin di
ng di trc WDM:

Nhng b iu hp Computer System Interface (SCSI) nh s dng mt trnh


iu khin " SCSI miniport ", khng s dng bt k ci no ca nhng chc
nng h tr nhn tiu chun v tin cy thay vo trn mt API c bit c
xut khu bi SCSIPORT.SYS hay SCSIPORT.VXD, nh trng hp c th.
Miniport th di ng gia nhng h thng.
Nhng card giao din Mng s dng mt NDIS miniport driver, m tin cy
ch ring trn mt API c bit c xut khu bi NDIS.SYS hay NDIS.VXD,
nh trng hp c th. Ti mt thi gian, cc trnh iu khin NDIS miniport
l di ng gia cc h thng, nhng tnh di chuyn c kh nhiu b mt
cho n by gi. Nhng trnh iu khin giao thc mng v nhng ci gi l
trnh iu khin " trung gian " m cung cp chc nng lc cng i theo qu o
xung quanh NDIS.

32/369
Tng quan v qun l v kim tra danh sch
Nu bn l mt gim c pht trin, hay nu bn chi trch nhim khc v chuyn mt
thit b phn cng kinh doanh, l vi suy ngh bn cn bit v nhng b iu
khin thit b. Bn cn quyt nh, trc ht, liu c phi bn cn mt trnh iu khin
ty bin v, nh vy th, cch thc no. Phn c trc cn phi gip bn vi quyt
nh , nhng bn c l mun thu mt c vn chuyn gia cho mc ch hn ch
ca vic khuyn bn trn im .

Nu s nh gi ca cc bn dn dt bn tin bn cn mt trnh iu khin ty thch,


bn ri cn nh v mt lp trnh vin thch hp. S tht bun ru l lp trnh trnh iu
khin WDM tng i cng, v ch c kinh nghim (v t tin!) nhng lp trnh vin
mi c kh nng lm n tt. Mt s cng ty c nhng lp trnh vin trnh iu khin
vng chc, nhng hu nh khng c th ti. Nu bn trong ch lm mi y, s la
chn c bn ca cc bn gia vic hun luyn ngi no l nhn vin ca cc bn,
vic thu mt lp trnh vin m c cn thit thnh vn , ha hn mt lp trnh vin
c vn hay hp ng, hay mt cng ty chuyn v nhn linh kin, ph tng pht trin
ti mt cng ty m chuyn v lp trnh trnh iu khin. Tt c nhng gii php ny c
nhng du cng v nhng s tr, v bn s c c s trng lng ca chng trn nhng
cn thit c nht ca cc bn.

Lp trnh Driver cn phi bt u ngay khi c mt c im k thut vng chc hp


l cho phn cng s lm vic nh th no. Bn cn phi mong i sa i c im
k thut khng r ca nhng khm ph kh a trong thi gian s pht trin trnh iu
khin, v bn cn phi cng mong i lp li phn cng vi chng trnh ca cc bn v
thit k trnh iu khin vi ln. Tnh linh hot v mt s bng lng trn bt u thc
s s gip bn.

Chun b c s h tng doanh nghip ca cc bn lm vic vi WHQL. Ti mt mc


ti thiu, (ci) ny s yu cu ang tn ti mt s Data Universal Numbering System
(DUNS) t Dun and Bradstreet (hay vic cung cp tng ng chng minh ca t chc
kinh doanh) v mt chng ch ch k s ha t Verisign. K t s ghi ny, nhng s
DUNS l t do, tr phi chng ch Verisign khng phi. V vic lm vic xuyn qua tt
c cc qu trnh ca nhiu cng ty s mt thi gian.

Nhng trnh iu khin c th Cung cp Thng k v thng tin qun l khc trong hai
cch. H thng con Windows Management Instrumentation (WMI) cung cp mt ngn
ng - v truyn ti- ng mn c lp cho nhng phn loi khc nhau ca d liu nh
phn. Microsoft thit lp nhng lp WMI tiu chun cho nhng kiu nht nh ca
thit b, v nhm con cng nghip ca ring cc bn c th thit lp nhng tiu chun
khc m ti ci trnh iu khin ca cc bn cn phi lm ph hp.

33/369
Hai cch ca vic cung cp thng tin qun l bi nhng phng tin ca bn ghi s kin
h thng, y l b phn ca Windows NT t s bt u v m a cho nhng ngi
qun tr mt cch nhanh phm vi ca kin thc v nhng iu kin khc thng m
xut hin trong qu kh gn y. Trnh iu khin ca cc bn cn phi bo co nhng
s kin m mt ngi qun tr quan tm n v c th lm ci g . Ngi no m
lp trnh driver ca cc bn cn phi tranh lun vi vi mt qun tr h thng giu kinh
nghim quyt nh nhng bn ghi s kin no, nh nh vy trnh lm ba bn bn
ghi vi th tc v thng tin khng ni bt. Tp tin kh thi driver ca cc bn s cng c
l bao gm vn bn ca thng bo trong mt ti nguyn thng bo a ng c bit, v
n l mt tng tt c mt ngi vit c hun luyn bin son vn bn .

Cui cng, ng coi nhng trnh iu khin ca cc bn nh nhng chi tit khng quan
trng. Vic c mt driver tt vi mt s ci t phng l t nht quan trng nh v ngoi
ca sn phm. t n n gin, nu driver ca cc bn ph hy h iu hnh, nhng
nh ph bnh s cnh bo cng khai, v bt c ai khng c nhng tng quan s ni gin
ang tr li sn phm ca cc bn cho nhng ca hng. Bn khng chin thng c nhng
bt k s t hng li no t nhng ngi m c h thng ph hy, thm ch mt ln,
bi v driver ca cc bn. V th l mt quyt nh cn th ti s pht trin trnh iu
khin short-fund c th d dng c mt kch tnh, hiu ng tiu cc trn hng di
ca cc bn trong nhiu nm n. Li khuyn ny l mt cch c bit quan trng cho
nhng nh sn xut phn cng trong nhng nc ang pht trin, u nhng nh qun
l c mt xu hng tm kim mi cch kh d ct (xn, ngt) nhng chi ph. Ti
gi rng s pht trin driver l mt ch ni s ra quyt nh trn nn chi ph khng
thch hp.

Tng kt, lp k hoch d n ca cc bn vi nhng ct mc sau y trong tm tr:

S nh gi ca trnh iu khin v s chn lc ca i hi ti nng lp trnh


c t lp trnh cho phn cng hon thnh y cho cng vic trnh iu
khin bt u
Mu ban u phn cng sn sng cho s th driver
Driver v hardware/firmware hot ng cng nhau nh trc y c d nh
File ci t (INF) c kim tra trn tt c cc h iu hnh
Nhng bng iu khin v phn mm ph tr khc lm
WMI v s kin bn ghi chc nng c lm v kim tra
Nhng t th WHQL c i qua v quyt nh c lm
Chng trnh ci t ty chnh lm (khng phi quyt nh b phn ca
WHQL)
Sn sng t chy nhng a v sn phm ngh nghip!

34/369
Bi 5: THC HNH MT S BI TP
C BN TRN VC++
Thc hnh mt s bi tp c bn trn VC++
Bi 1

Cc to Project trn VC++

Bi 2

Vit c chng trbinh n gin trn VC++; cng 2 s

Bi 3

To chng trnh VC++, vit chng trnh gii phng trnh bc 2.

35/369
Bi 6: CC K THUT LP TRNH C
BN
Mi trng lp trnh kiu Kernel Mode
Hnh 3-1 minh ha mt s nhng thnh phn to ra h iu hnh XP Microsoft
Windows. Mi thnh phn hm dch v n c tn bt u vi mt tin t c bit 2- k
t, 3- k t:

Qun l vo/ra (Tin t Io) cha ng nhiu hm dch v m nhng trnh iu


khin s dng, v l iu m ti bn lun trong cun sch ny.

M un Cu trc Qu trnh (Tin t Ps ) to ra v qun l nhng lung kiu nhn. Mt


trnh iu khin WDM bnh thng c l s dng Mt lung c lp nhiu ln
ct ngn Mt thit b khng c kh nng ca vic pht sinh nhng ngt, v (cho) nhng
mc ch khc.

Qun l b nh ( Tin t Mm) iu khin nhng bng trang m nh ngha nh


x (ca) nhng a ch o ln trn b nh vt l.
Thi hnh ( Tin t Ex) cung cp qun l tt c cc dch v ng b ha. Ti s
bn ti cc vn thc hin cc ch lnh chng tip theo, bao hm nhng
dch v ng b ha.
Qun l i tng ( Tin t Ob ) cung cp kim sot tp trung qua nhiu i
tng d liu m khi Windows XP hot ng. Nhng iu khin WDM tin cy
trong qun l i tng lm cho mt tnh th li m ngn nga mt i
tng khng bin mt trong khi ngi no vn cn s dng n v chuyn
i phn i tng qua con tr ti nhng i tng i din.
Bo mt tham chiu m hnh ( Tin t Be) cho php iu khin h thng tp tin
thc hin nhng s kim tra bo mt. Mt vi iu khin khc th phn phi
vi nhng s lin quan bo mt trc thi gian mt yu cu vo/ra t n iu
khin WDM, v vy Ti ang bn lun nhng hm trong sch ny.
Thnh phn " th vin thc thi " ( Tin t Rtl) cha ng nhng chng trnh
thng dng, nh danh sch v nhng th tc qun l chui, nhng trnh iu
khin Kernel - mode c th s dng thay v ANSI- tiu chun bnh thng
nhng th tc th vin. Phn ln, thao tc nhng hm ny hin nhin thng qua
nhng tn ca n v nhng hiu bit ca bn khi s dng chng.
Windows XP thi hnh nhng ngn ng API ca Kernel - mode c gi khi s
dng nhng tn th tc m bt u vi tin t Zw. Nhng ti liu DDK dung
mt vi k hiu hn ZwXxx, Tc l l th m gn lin vi ni ng k v s
truy nhp h s. Nhng hm c bn lun trong chng ny.

36/369
Nhn XP Windows ( Tin t Ke ) l tt c s ng b ha mc thp (ca)
nhng hot ng gia nhng lung v nhng b x l xut hin. KeXxx c
bn ti trong chng tip theo.
Nhiu lp di ca h iu hnh, n c tc dng h t h thng khi v ch
ngh ngi, l lp tru tng ha phn cng ( hay HAL, tin t Hal). Tt c
nhng thnh phn h iu hnh ca my tnh c lin kt vi nhau trong
HAL. HAL gi ngt trong nhng qu trnh lm vic, kt ni cc thit b vo/
ra v nhng thit b lu tr khc. Thay v vic kt ni trc tip ti phn cng
ca my tnh, iu khin WDM gi l nhng hm trong HAL thc hin.

Hnh 3-1. Tng quan ca Kernel mode h tr nhng th tc

S dng cc th vin chc nng chun Run-Time

Windows NT, kin trc s a thch m khng s dng trnh iu khin run_time cc th
vin c cung cp bi nh cung cp ca chng trnh bin dch C. Trong mt phn,
ban u khng chp ny sinh t thi gian rt n gin. Windows NT c thit k
ti mt thi gian khi khng c ANSI tiu chun cho nhng g thuc mt hm chun th
vin v khi rt nhiu trnh bin dch tn ti, vi mi tng ring ca nhng g bao gm
s bnh tnh v c o ring chun cht lng.

Yu t khc l th vin chun run_time i khi da vo khi to rng c th xy ra ch


trong mt ngi s dng ch -ng dng v i khi c trin khai thc hin trong
mt si-a-khng an ton hay khng an ton cch.

37/369
Mt Nhc nh v nhng tc dng ph

Cc "functions" m bn s dng trong mt trnh iu khin c nh ngha l macros


trong DDK tiu file. V d, cc m sau y:

int a = 2, b = 42, c;

c = min(a++, b);

C bn bn c th khng bit khi no cc DDK s s dng mt macro v n s khi tuyn


b mt thc t hm bn ngoi. i khi mt dch v hm s l mt nn tng v m cho
mt s hm v mt cuc gi cc nn tng. Hn na, Microsoft l min ph thay i
ngha ca n trong tng lai. Do , bn nn lm theo quy nh ny khi lp trnh cho
trnh iu khin WDM : Khng bao gi s dng mt biu hin c phn ng ph nh l
mt i s cho mt ht nhn-ch dch v hm

38/369
Trnh by li (Li x l)
Li lun lun pht sinh trong chng trnh. Mt s ngi trong s h bt u vi chng
trnh li, hoc trong m ring ca chng ti hoc cc thnh vin trong-ch gi cc
ng dng m m ca chng ti. Mt s ngi trong s h lin quan n h thng np
hoc lm ngay trong tiu bang ca phn cng. Bt nguyn nhn, hon cnh khng bnh
thng l mt nhu cu linh hot ca chng ti phn hi t m

Trong phn ny, ti s m t ba kha cnh ca x l li: tnh trng m s, ngoi tr cu


trc x l, v kim tra li. Nhn chung, ch h tr ht nhn-thi quen bo co li
khng mong mun bng cch tr ra mt m trng thi, trong khi h bo co d kin cc
bin th bnh thng trong dng chy bng cch tr ra mt gi tr s Boolean hoc khc
hn l mt trng thi thc m

Cu trc x l ngoi l cung cp mt tiu chun nht dn sch sau khi thc s khng
mong mun cc s kin, chng hn nh dereferencing mt ngi dng khng hp l-
ch tr, hoc trnh ng xe m cc h thng thng thng ensues sau khi nhng
s kin. Mt li kim tra ni b l tn gi cho mt tht bi thm cho l mt h thng
tt l ch cha khi.

Codes

Kernel_mode h tr thi quen (v m ca bn ,cho rng vn ) cho bit thnh cng


hay tht bi bng cch tr ra mt m trng thi ca h gi. NTSTATUS mt gi tr l
32-bit integer gm mt s subfields, nh minh ha trong hnh 3-2. Cao-bit 2 trt t biu
cc mc nghim trng ca cc iu kin c bo co-thnh cng, thng tin, cnh
bo, hoc li. Ti s gii thch s tc ng ca cc khch hng sm c

Cc thit b m cho bit thnh phn h thng ngun gc tin nhn v decouple c bn
phc v pht trin cc nhm t mi khi ni n s in thoi gn m. Trong phn
cn li trong tnh trng m 16-bit 'gi tr-cho bit chnh xc iu kin c bo co.

39/369
Bn nn lun lun kim tra tnh trng tra ra t th tc m h cung cp. Ti ang dng
kt qu nguyn tc ny thng xuyn trong mt s cc on m ti cho bn bi v bao
gm tt c cc li cn thit x l m thng xuyn che lp cc expository

ch ca on ny. Nhng bn khng m phng thc hnh ng

Nu bit-cao, trt t ca mt m trng thi l 0, bt k s bit cn li c th c thit


lp v cc m vn cn cho bit s thnh cng. Do , khng bao gi cn so snh vi
tnh trng m s 0 xem liu bn ang i ph vi s thnh cng-thay v, s dng cc
macro NT_SUCCESS:

NTSTATUS status = SomeFunction(...);

if (!NT_SUCCESS(status))

//handle error

Khng ch lm bn mun kim tra tnh trng m s m bn nhn c t thi quen


bn gi , nhng bn cng mun tr ra trng thi m s th tc bn gi. Trong chng
trc, ti x l vi hai trnh iu khin subroutines-DriverEntry v AddDevice-c
nh ngha l c hai li NTSTATUS m

Nh ti tho lun, bn mun tr v STATUS_SUCCESS nh s thnh cng t nhng


thi quen. Nu c g sai, bn thng mun tr ra mt m trng thi thch hp, m

40/369
i khi l cng mt gi tr tr ra cho bn. V d, y l mt s bc u tin trong hm
AddDevice , vi tt c cc li kim tra bn tri:

NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)

NTSTATUS status;

PDEVICE_OBJECT fdo;

status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION),

NULL, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE,

&fdo);

if (!NT_SUCCESS(status))

KdPrint(("IoCreateDevice failed - %X\n", status));

return status;

PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;

pdx->DeviceObject = fdo;

pdx->Pdo = pdo;

pdx->state = STOPPED;

IoInitializeRemoveLock(&pdx->RemoveLock, 0, 0, 0);

status = IoRegisterDeviceInterface(pdo, &GUID_SIMPLE, NULL,

&pdx->ifname);

if (!NT_SUCCESS(status))

41/369
KdPrint(("IoRegisterDeviceInterface failed - %X\n", status));

IoDeleteDevice(fdo);

return status;

1. IoCreateDevice chng ti s tr li trong cng mt m trng thi n cho


chng ti. Lu vic s dng cc macro NT_SUCCESS nh c m t trong
vn bn.
2. N i khi l mt tng tt, c bit l mt kh nng g li trong trnh iu
khin , in tnh trng li no bn khm ph. Ti s tho lun v cch s dng
chnh xc ca KdPrint sau trong chng ny (trong phn "Mu Debugging
Easier" ).
3. IoInitializeRemoveLock, tho lun trong Chng 6, khng th khng thnh
cng. Do , khng cn phi kim tra m trng thi. Ni chung, hu ht cc
hm tuyn b vi cc loi VOID ang c trong cng mt loi "khng th
khng" . Mt s hm VOID c vn bn b tht bi do nui mt ngoi l, nhng
cc ti liu DDK rng hnh vi rt r rng.
4. IoRegisterDeviceInterface nn khng thnh cng, chng ti c mt s ngu
nhin lm trc khi chng ti quay tr li gi ; c th,chng ti phi gi
IoDeleteDevice tiu dit cc thit b i tng, chng ti ch cn to ra.

Bng 3-1 cho thy nhng th quan trng nht i vi tnh trng m s.

42/369
S khc bit gia mt li v cnh bo c th c ng k. V d, khng mt
METHOD_BUFFERED kim sot hot ng (xem Chng 9) vi
STATUS_BUFFER_OVERFLOW-a-gy ra cc cnh bo I / O Trng i din sao
chp d liu i vi ngi s dng ch -buffer. Vic khng cng mt hot ng vi
STATUS_BUF FER_TOO_SMALL-mt li-nguyn nhn ca I / O Trng i din
cho bt k khng c sao chp d liu.

Gii quyt Cc ngoi l c cu trc

Gia nh ca h iu hnh Windows cung cp mt phng php x l iu kin c bit


gip bn trnh nhng tim nng h thng treo. Tch hp cht ch vi cc bin ca m
My pht in, cu trc x l ngoi l cho php bn d dng t ra mt s bo v trn
cc phn ca m ca bn v x l gi ngoi tr khi c g sai trong phn guarded

Cu trc ngoi l x l cng cho php bn d dng cung cp cc ti liu kim m bn


c th chc chn s lun lun c thc hin nh th no khng c vn kim sot l
guarded mt phn ca m. Rt t cc bui hi tho ca ti c hc sinh quen thuc
vi cu trc ngoi l, v th ti s gii thch mt s Nhng vn c bn ca y. M
bn c th vit tt hn, thm bulletproof m nu bn s dng nhng tin nghi. Trong
nhiu tnh hung, cc tham s m bn nhn c trong mt trnh iu khin WDM
c qun trit vetted do cc m v s khng cau

Tt hng v c th, do , cc ch c bn c th s dng cc cng c Ti m


t trong phn ny. Nh l mt quy lut chung, tuy nhin, bn lun lun mun bo v ti
liu tham kho trc tip vi ngi s dng b nh o-ch vi mt cu trc khung
ngoi l. Nhng ti liu tham kho xy ra khi bn trc tip tham chiu b nh v khi bn
gi MmProbeAndLockPages, ProbeForRead, v ProbeForWrite, v c l nhng thi
gian khc

M s mu

Cc SEHTEST mu minh ho driver c kh ca cc cu trc ngoi l trong mt trnh


iu khin WDM. Ngoi l no c th tr thnh trapped

Gary Nebbett nghin cu cc cu hi trong c trng hp ngoi l c th c


trapped vi cc cu trc ngoi tr c ch v bo co kt qu ca mnh trong mt
newsgroup ng bi nhiu nm trc y. SEHTEST cc mu hp nhng g ng c
hc. Ni tm li, cc trng hp ngoi l sau y s c khi h b bt li xy ra ti
IRQL nh hn hoc bng DISPATCH_LEVEL (lu rng mt s trong s ny l c th
cho cc b x l Intel x86):

Bt k k do ExRaiseStatus v lin quan hm li d

43/369
dereference khng hp l cho ngi dng tr-ch b nh

Debug hoc Breakpoint ngoi l

Integer overflow (hng dn nhp)

opcode khng hp l

Lu rng mt tham chiu n mt ch khng hp l ht nhn-tr dn trc tip n


mt li kim tra v c th khng c trapped. Tng t, mt chia-do-hay khng ngoi
tr mt ngoi l RNG BUC hng dn dn ti mt li kim tra.

Chng trnh ht nhn-ch s dng cu trc ngoi tr trng hp ngoi l bng cch
xy dng khung trn cng mt cy rm c s dng cho cc i s qua, subroutine
gi in thoi, v t ng cc bin. Mt dnh x l ng k im hin ti ngoi tr
khung. Mi phng trong khung im n trc khung.

Bt c khi no mt trong cc ngoi l xy ra, ht nhn tm kim trong danh sch cc


ngoi l cho mt ngoi tr khung handler. N s lun lun tm thy mt bi v c mt
ngoi l khung ti rt trn cng ca stack m s x l bt k khc unhandled ngoi l.
Mt khi ht nhn nm mt ngoi l handler, n unwinds vic thc hin v ngoi tr
khung stacks song song, ku gi s x l dc theo ng i. Sau , n iu khin cho
cc ngoi l handler.

Khi bn s dng bin ca Microsoft, bn c th s dng Microsoft m rng cho C / C


+ + ngn ng m n mt s trong cc phc tp ca nguyn liu lm vic vi cc h
iu hnh primitives. Bn s dng __try tuyn b ch mt phc hp tuyn b nh
l guarded c th cho mt ngoi tr khung, v bn s dng hoc cc __finally tuyn
b thnh lp mt handler hoc chm dt cc __except tuyn b thnh lp mt ngoi l
handler.

u tin cc my tnh thi guarded trong c th. Khi kim sot cc l guarded c th cho
bt c l do g, my tnh handler thi chm dt. Xem Hnh 3-3.

44/369
Hnh 3-3. Kim sot dng chy ca trong mt th-cui cng khi.

y l mt trong rt n gin Illustration:

LONG counter = 0;

__try

++counter;

__finally

--counter;

KdPrint(("%d\n", counter));

Guarded u tin trong c th v thi increments quy bin t 0 n 1. Khi kim sot "b
qua" quyn brace cui ca guarded c th, chm dt handler thi v decrements cp
quay li 0. Gi tr do s c in ra 0. y l bin th hi phc tp hn:

VOID RandomFunction(PLONG pcounter)

45/369
__try

++*pcounter;

return;

__finally

--*pcounter;

Kt qu ca hm ny, khng c thay i cc nguyn cui ca pcounter tr: bt c


khi no kim sot cc l guarded c th cho bt c l do g, bao gm mt tuyn b tr
li hoc mt goto, chm dt handler thi. y l nhng s tng dn thn trng trong c
th truy cp v thc hin mt tr li.

static LONG counter = 0;

__try

++counter;

BadActor();

__finally

--counter;

46/369
Hy th-Ngoi tr Blocks Cc cch khc s dng cu trc ngoi l bao gm vic x
l mt th-ngoi tr khi:

__try

<guarded body>

__except(<filter expression>)

<exception handler>

EXCEPTION_EXECUTE_HANDLER c nhiu bng 1 v cho cc h iu hnh


chuyn giao kim sot ca bn ngoi tr handler. Nu handler t ng ca bn thng qua
vic kt thc quyn brace, tip tc kim sot ca bn trong chng trnh ti cc tuyn b
ngay lp tc sau phi brace. (Ti thy Platform SDK ti liu hng dn cho rng
c hiu lc tr v kim sot cc im ca cc ngoi l, nhng l khng chnh xc

EXCEPTION_CONTINUE_SEARCH c nhiu bng 0 v cho cc h iu hnh m


bn c th khng x l cc ngoi l. H thng gi hm qut up the stack ang tm kim
cc handler khc. Nu khng c ngi cung cp mt handler cho cc ngoi l, mt
h thng sp s xy ra.

EXCEPTION_CONTINUE_EXECUTION c nhiu bng -1 v cho cc h iu


hnh tr li im, ni cc ngoi l c nng ln. Ti s c thm mt cht ni
v vic ny biu hin gi tr thm vo mt t. Hy xem Hnh 3-4 cho cc con ng
c th kim sot trong v xung quanh l mt th-tr khi.

Bottom of Form

Bottom of Form

47/369
Hnh 3-3. Lung ca iu khin khi try - finally .

y l mt v d n gin:

LONG counter = 0;

__try

++counter;

__finally

--counter;

KdPrint(("%d\n", counter));

Trc tin thc thi phn thn v tng bin m t 0 ln 1. Khi iu khin drops
through cui ca phn thn, kt thc qu trnh x l v gim bin m ti 0. Bi vy
gi tr in ra s l 0.

y l mt v d phc tp hn.

48/369
VOID RandomFunction(PLONG pcounter)

__try

++*pcounter;

return;

__finally

--*pcounter;

Kt qu ca hm ny l khng thay i gi tr nguyn cui ca con tr: bt c lc no


iu khin di dn phn thn vi bt k l do gi, bao gm mt cu lnh tr v hoc mt
goto, vic thc thi kt thc. y l phn tng bin m v tr ra gi tr. on code tip
theo thc thi v gim bin m. sau chng trnh con s thc hin li.

Mt v d hon chnh ca khi try-finally:

static LONG counter = 0;

__try

++counter;

BadActor();

__finally

49/369
{

--counter;

Chng ta gi y l mt hm, BadActor, n s xut hin mt vi s sp xp ca ngoi l


kch hot mt stack hot ng. Nh mt phn ca tin trnh ngh thc hin v ngoi l
ngn xp, h iu hnh s gi m code ca chng ta khi phc li bin m ti gi tr
trc n. h thng s tip tc gii phng stack, v vy bt c cu lnh no vit sau khi
finally s khng c thc hin.

Khi Try Except.

Mt cch khc s dng cu trc x l ngoi l l khi try-Except

__try

<guarded body>

__except(<filter expression>)

<exception handler>

Phn thn ca khi try-except l m c sc mnh ph v nhng pht sinh ngoi l. C


l l bn ang gi ti phn chnh ca hm nh MmProbeAndLockPages s dng con tr
chuyn ho t ch ngi dng khng cn kim tra gi tr r rng. C th bn c l do
khc. Trong mi trng hp nu bn qun l tt c cc cch thng qua phn thn khng
c li, iu khin s tip tc m code x l ngoi l phn sau. Bn s ngh trng hp
ny tr ln bnh thng. Nu mt ngoi l xut hin trong m code ca bn hoc trong
bt k tin trnh con no m bn gi, tuy nhin, h iu hnh s gii phng stack, nh
gi biu thc trong cu lnh Except. Nhng biu thc ny sinh ra mt trong nhng gi
tr sau:

EXCEPTION_EXECUTE_HANDLER c gi tr bng 1 v thng bo cho h


iu hnh chuyn iu khin ti vic x l ngoi l ca bn. Nu vic x l

50/369
ca bn tht bi, iu khin s tip tc chng trnh ca bn cu lnh ngay
sau .( Ti xem ti liu Platform SDK ni v hiu ng m iu khin tr ra
ngoi l ti im ca ngoi l, nhng iu khng ng)
EXCEPTION_CONTINUE_SEARCH c gi tr bng 0 v thng bo vi h
iu hnh rng bn khng th x l ngoi l. H thng s qut qua stack tm
kim x l khc. Nu khng ai cung cp mt x l no cho ngoi l th mt h
thng v s xy ra.
EXCEPTION_CONTINUE_EXECUTION c gi tr bng -1 v thng bo cho
h iu hnh tr ra mt dim ni m ngoi l c sinh ra. Ti s c mt bi
ni v gi tr biu thc ny nhiu hn na.

Nhn hnh 3-4 c th iu khin ng dn trong v xung quanh mt khi try-except.

Hnh 3-4. Flow of control in a try-except block.

Cho v d, bn c th bo v chnh bn khi nhn mt con tr sai bng s dng m code


sau y.

PVOID p = (PVOID) 1;

__try

KdPrint(("About to generate exception\n"));

ProbeForWrite(p, 4, 4);

KdPrint(("You shouldn't see this message\n"));

51/369
}

__except(EXCEPTION_EXECUTE_HANDLER)

KdPrint(("Exception was caught\n"));

KdPrint(("Program kept control after exception\n"));

ProbeForWrite kim tra mt vng d liu cho tnh hp l. v d ny, n s gy ra mt


ngoi l bi v con tr m chng ta cung cp cha c lin kt ti 4 byte. Vic x l
ngoi l tng tc iu khin. iu khin sau s thc hin cu lnh sau x l ngoi l
v tip tc chng trnh ca bn.

Trong v d trc, c bn c tr ra gi tr EXCEPTION_CONTINUE_SEARCH,


h iu hnh tip tc gii phng stack tm kim mt x l ngoi l. Khng c m
code x l ngoi l ca bn cng khng c m sau n c thc thi: Mi h thng
s b ph hu hoc s c x l ngoi l mc cao hn. Bn khng nn tr v
EXCEPTION_CONTINUE_EXECUTION trong phn nhn v bn khng c cch no
d thay i nhng nguyn nhn gy ra ngoi l cho php th li.

Ch rng bn khng th by nhng ngoi l s hc, hoc nhng trang li lin kt mt


con tr kiu nhn sai, bng vic s dng cu trc ngoi l. Bn ch cn vit m khng
pht sinh nhng ngoi l nh vy. l lm th no trnh chia cho 0.

Nh v d sau y.

ULONG numerator, denominator; // <== numbers someone gives you

ULONG quotient;

if (!denominator)

<handle error>else

quotient = numerator / denominator;

Nhng lm th no con tr c th n ti bn t phn khc ca nhn? khng phi


l hm m bn c th s dng kim tra gi tr ca mt nhn con tr. Bn cn ch
nhng quy tc di y:

52/369
Theo cch thng thng, gi tr thc m mt nhn thnh phn a cho bn.

Ti khng cho rng bn khng nn chia nh on m ca bn vi cu lnh ASSERT -


bn nn bi v bn c th khng hiu tt c bn trong v bn ngoi cch lm vic ca
thnh phn nhn khc nh th no. Ti cho rng bn khng cn nng trnh iu khin
ca bn vi s phng th qu mc chng li li ch khc, c kim tra k, mt phn
ca h thng tr khi bn cn lm vic xung quanh mt li.

V nhng hn ch trn bn s dng hai biu thc ny nh th no trong chng trnh


ca bn, bn s hu nh chc chn mun s dng chng trong mt hm gi mt vi
hm iu kin, ging nh:

LONG EvaluateException(NTSTATUS status, PEXCEPTION_POINTERS xp)

__except(EvaluateException(GetExceptionCode(),

GetExceptionInformation()))

a ra ngoi l

Chng trnh li l mt cch bn c th a ra ngoi l m gi cu trc x l ngoi l.


Chng trnh ng dng l quen thuc vi Win32 hm API a ra ngoi l, ci m cho
php bn to ra mt ci g ngoi l cho chnh bn. trnh iu khin WDM bn c
th gi tin trnh lng nghe trong bng 3-2. ti khng a cho bn mt v d c th
gi hm ny bi v nhng l do sau:

Ni c th, a ra ngoi l khng phi l cch tt ni cho i tng gi ca bn thng


tin m bn khm ph ra trong vic x l cc tin trnh thng thng. N tt hn nhiu

53/369
tr v mt trng thi m, thm ch nh th l s ch dn t bn ngoi kh c hn. Bn
nn trnh nhng ngoi l bi v my mc rt dt tin. Thm ch gi ca khung ngoi l
l quan trng v mt vi th cn trnh khi bn c th.

Bng 3-2. Dch v hm cho Raising


Exceptions
Service Function Description
ExRaiseStatus Raise exception with specified status code
ExRaiseAccessViolation Raise STATUS_ACCESS_VIOLATION
Raise
ExRaiseDatatypeMisalignment
STATUS_DATATYPE_MISALIGNMENT

V d thc t

Mc d ph tn ca vic ci t ln v ph hng mt ngoi l, bn phi s dng quy tc


cu trc ngoi l trong mt trnh iu khin trong trng hp c bit.

Mt trong nhng ln bn phi thit lp mt x l ngoi l l khi bn gi


MmProbeAndLockPages tm kim trang cho mt b nh danh sch mieu t(MDL)
bn to ra:

PMDL mdl = MmCreateMdl(...);

__try

MmProbeAndLockPages(mdl, ...);

__except(EXCEPTION_EXECUTE_HANDLER)

NTSTATUS status = GetExceptionCode();

IoFreeMdl(mdl);

return CompleteRequest(Irp, status, 0);

54/369
}

(CompleteRequest l mt hm gip ti s dng x l i hi hon thnh I/O.


Chng 5 gii thch tt c v yu cu I/O v hon thnh chng.)

Ln khc khi s dng mt x l ngoi l l khi bn mun truy cp b nh ngi dng


s dng mt con tr t ngun khng ng tin. Trong v d di y, cho rng bn thu
c con tr p t mt chng trnh ngi dng v chc chn n tr ti mt s nguyn:

PLONG p; // from user-mode

__try

ProbeForRead(p, 4, 4);

LONG x = *p;

__except(EXCEPTION_EXECUTE_HANDLER)

NTSTATUS status = GetExceptionCode();

Bug Checks

55/369
Nhng li khng th phc hi c trong kiu nhn c th biur th chnh n trong ci
goi l mn hnh xanh ca s cht(BSOD) l tt c qu quen thuc i vi lp trnh
vin. Hnh 3-5 l mt v d .

Bn trong, nhng li ny c gi l kim tra ri,sau dch v hm bn s dng


chun on s c ca chng: KeBugCheckEx. c tnh chnh ca s kim tra ri l h
thng ng chnh n trong th t mt cch nh hp l v hin ti BSOD. Mt BSOD
xut hin h thng s khng hot ng v phi khi ng li

Hnh 3-5. M hnh xanh ca s khng hot ng

Bn c th gi KeBugCheckEx nh sau:

KeBugCheckEx(bugcode, info1, info2, info3, info4);

bugcode l mt gi tr s xc nh nguyn nhn li v info1, info2, vn vn l nhng s


m xut hin trn mn hnh BSOD gip ngi lp trnh hiu c cc li. Hm ny
khng tr ra gi tr.

Nh mt ngi pht trin bn khng c thng tin t mn hnh xanh. Nu bn may mn.
thng tin s bao gm c hng dn been trong trnh iu khin ca bn. Sau bn
c th xem xt v tr ny trong nhn trnh g ri, c l, suy lun c th thc hin c
v kim tra ri. Chnh kim tra ri ca Microsoft xut hin trong bugcodes.h S gii
thch v m ca h c th tm thy trong Nhng kin thc c bn Q103059. a fuller

56/369
explanation of the codes and their various parameters can be found in Knowledge Base
article Q103059, Descriptions of Bug Codes for Windows NT, ci m c sn trong
MSDN, gia nhng ch khc.

V d

V d iu khin BUGCHECK cung cp cch lm th no gi KeBugCheckEx. Ti


s dng n pht sinh hnh nh hnh 3-5.

Bn c th to debug-check cho chnh bn nu bn mun. Nhng gi tr ca Microsoft l


nhng gi tr n gin bt du t 1(APC_INDEX_MISMATCH) v (hin gi) m rng
dn 0xF6 (PCI_VERIFIER_DETECTED_VIOLATION), cng vi mt s ci khc.

to ra m kim tra ca mnh, dnh ngha mt hng s s nguyn nh nu bn trng


thi STATUS_SEVERITY_SUCCESS , nhng nhng yu cu khc ca khch hng
hoc mt m khc khng.

V d:

#define MY_BUGCHECK_CODE 0x002A0001

KeBugCheckEx(MY_BUGCHECK_CODE, 0, 0, 0, 0);

Bn s dng mt m trng thi khc 0 (42 trong v d) hoc c ca khch hng(ci m


ti vit 0 trong v d ny) v vy m bn c th thng bo chnh m ca bn t mt ngi
s dng Microsoft.

By gi ti ni cho bn cch lm th no to BSOD cho chnh bn, cho php ti ni khi


no bn lm n: khng bao gi. Hoc trong khi xy dng kim tra ca trnh iu khin
s dng trong sut bn trong qu trnh g ri. Bn v ti u khng chc chn vit
mt trnh diu khin m s pht hin mt li nghim tc n ni ly xung h thng l
cch gii quyt duy nht. N s tt hn nhiu g li( s dng g li ti s m t trong
chng 14 ) v tr ra mt m tnh trng.

Ch rng ngi dng cui c th cu hnh hnh ng ca KeBugCheckEx trong nhng


s thit lp cho my tnh ca ti. Ngi s dng c th chn khi ng mt cch t
ng hoc pht sinh BSOD. Ngi dng cui c th nh vy chn vi mc ca chi tit(
k c khng) cho mt file.

57/369
Qun l b nh (Memory Management )
chng ny, ti s bn v ch qun l b nh. Windows XP chia ct vng a ch
thc t chia ct bn trong bng vi cch. Mt cch chia - rt bo mt v ton vn l a
ch ngi dng v a ch nhn. Mt cch chia khc, m s dng hu ht nhng khng
tt lm l gia trang nh v khng phaitrang nh. Hu ht a ch ngi s dng v vi
a ch kiu nhn tham chiu dn nh m Qun l b nh i ti v t a trong ton
b thi gian, trong khi mt vi a ch kiu nhn lun lun lin kt ti nh trong b
nh vt l. T Windows XP cho php nhng phn ca trnh iu khin t nh, ti s
gii thch cch lm th no iu khin nh ca trnh iu khin ca bn ti mt thi
im bn xy dng trnh iu khin v chy n. Windows XP cung cp mt s phog
thc qun l b nh. Ti s m t hai hm dch v c bn ExAllocatePoolWithTag
v ExFreePool m bn s dng phn chia v gii phng mt cch ngu nhin. Ti
s gii thch nguyn thu m bn s dng t chc b nh v trong nhng danh sch
lin kt ca cu trc. Cui cng ti s gii thch khi nim mt danh sch m cho php
bn phn chia c hiu qu.

User-Mode and Kernel-Mode Address Spaces

Windows XP v Microsoft Windows 98/Me chy trn nhngmy tnh m h tr mt


vng a ch thc t ni m a ch o c v ti b nh vt l hoc mt nh bn
trong file tro i trn da cng. Th tc n gin ho nhng vn , bn c th ngh v
a ch o nh chia ct thnh hai phn: mt phaanf kiu nhn v mt phn kiu ngi
dng. Nhn hnh 3-6.

Hnh 3-6. Thnh vin-ht nhn v ch -ch ca phn khng gian a ch. Mi ngi
s dng ch x l c a ch bi cnh ring ca mnh, m bn ca ngi s dng
ch o-a ch duy nht cho mt b su tp ca vt cht trang khung. Ni cch khc,
ngha ca bt k a ch ring o thay i t mt cht thi gian tip theo nh l
Windows XP Scheduler tc t mt si mt trong qu trnh vo mt si khc trong qu

58/369
trnh. Mt phn ca cng vic trong khu chuyn i l thay i cc trang bng c
s dng bi mt x l h gii thiu n cc lung ca qu trnh bi cnh. It's thng
khng WDM , mt driver s thc hin trong cng mt bi cnh nh l si xng ca
I / O yu cu n x l.

Chng ta ni rng chng ti ang chy trong bi cnh arbitrary si, nu chng ta khng
bit chc chn s cho qu trnh m hin nay ngi s dng ch a ch bi cnh thuc.
Trong bi cnh arbitrary si, chng ti ch n gin c th khng c s dng mt a
ch m o thuc vi ngi s dng ch bi v chng ti c th khng c bt k
tng vi nhng g vt l b nh n c th im. Trong s ny xem khng chc chn,
nhn chung chng ti phi tun theo cc quy nh sau y trong mt chng trnh driver:
Khng bao gi (tt, my khi) ngi trc tip tham chiu-ch b nh

Ni cch khc, khng c mt a ch m mt ngi s dng ch -cung cp cc


ng dng v cha tr cho rng nh l mt a ch tr rng chng ti c th trc tip
dereference. Ti s tho lun trong chng sau mt vi k thut truy cp d liu m
m bt ngun ch ngi dng. Tt c chng ti cn phi bit ngay by gi, tuy
nhin, chng ti ang l (gn nh) lun lun c c bng cch s dng ht nhn-ch
a ch o bt c khi no chng ti mun truy cp vo b nh ca my tnh. Bao ln
C mt trang?

Trong mt h thng b nh o, h iu hnh t chc vt l b nh v cc vng trao i


vo tp tin nh-kch thc trang khung. Trong mt WDM trnh iu khin, bn c th
s dng t c PAGE_SIZE cho bn bit lm th no l mt trang ln. Trong mt s
my tnh Windows XP, mt trang l 4096 bytes di; trong nhng ngi khc, it's 8192
bytes di. A lin quan n vic t tn PAGE_SHIFT kch thc bng cc trang nh l
mt sc mnh ca 2. l:

PAGE_SIZE == 1 << PAGE_SHIFT

Cho s tin nghi ca bn, bn c th s dng mt vi preprocessor macros m ca bn


trong khi bn ang lm vic vi cc kch thc ca mt trang web:

ROUND_TO_PAGES trong vng mt kch thc byte n trang k tip cao hn-ranh
gii. V d, ROUND_TO_PAGES (1) l 4.096 trn mt 4-KB-trang my tnh.

BYTES_TO_PAGES xc nh bao nhiu trang c yu cu t chc mt s byte, bt


u t bt u ca mt trang. V d, BYTES_TO_PAGES (42) s l 1 trn tt c cc nn
tng, v BYTES_TO_PAGES (5000) s l 2 trn mt s nn tng v 1 v nhng ngi
khc. BYTE_OFFSET s tr v byte b p phn ca mt a ch o. l, tnh ton
ca n bt u b p trong vng mt s trang khung ca mt a ch. Ngy 4-KB-trang,
my tnh, BYTE_OFFSET (0x12345678) s c 0x678

59/369
PAGE_ALIGN vng mt o a ch xung mt trang ranh gii. Ngy 4-KB-trang,
my tnh, PAGE_ALIGN (0x12345678) s c 0x12345000.

ADDRESS_AND_SIZE_TO_SPAN_PAGES tr ra s trang khung chim c xc


nh bi mt s byte, bt u t mt a ch o. V d, cc tuyn b
ADDRESS_AND_SIZE_TO_SPAN_PAGES (0x12345FFF, 2) l 2 trn mt 4-KB-
trang my v 2 byte chiu di mt trang ranh gii.

nh s trang v nh s trang B nh

Ton b s im ca mt h thng b nh o l bn c th c c mt khng gian a


ch o l nhiu ln hn s lng b nh vt l trn my tnh. thc hin iu ny
feat, Trng i din cc B nh nhu cu trao i trang khung trong v ngoi ca vt
l b nh.

Cc th loi "phi c c dn" cng c rng ln hn nhiu hn l ch cc trang li x


l. Windows XP cho php phn cng interrupts xy ra gn bt k lc no, bao gm
mt trang li trong khi ang c phc v. Nu iu ny khng c nh vy, cc trang
li handler s khng th c hoc vit trang t mt thit b s dng mt gin on

V vy, mi phn cng gin on dch v thng phi c nonpaged trong b nh.
Cc thit k ca Windows NT, bao gm cc quyt nh ngay c thm thi quen trong
nonpaged danh mc bng cch s dng mt nguyn tc n gin: M thi hnh ti hoc
gin on trn mc yu cu (IRQL) DISPATCH_LEVEL trang c th khng gy ra
li lm.

Ti s xy dng trn nguyn tc ny trong chng k tip. Bn c th s dng


PAGED_CODE preprocessor v m (trong wdm.h) gip bn khm ph cc hnh vi
vi phm cc quy nh ny trong kim tra xy dng ca driver ca bn. V d:

NTSTATUS DispatchPower(PDEVICE_OBJECT fdo, PIRP Irp)

PAGED_CODE()

PAGED_CODE cha cc iu kin bin son. Trong khi kim tra-xy dng, mi
trng, n in mt tin nhn v to ra mt ng tht bi nu IRQL hin nay l qu cao.
Trong min ph-xy dng, mi trng, n khng lm bt c iu g. hiu l do ti
sao PAGED_CODE rt hu ch, tng tng rng DispatchPower nhu cu cho mt s
l do c nonpaged nhng b nh rng bn c misplaced n trong b nh paged

60/369
Nu h thng xy ra DispatchPower gi ti mt thi gian khi trang cha n khng
phi l hin nay, mt trang li s xy ra, theo sau l mt li kim tra. Li m
kim tra s c pretty uninformative (IRQL_NOT_LESS_OR_EQUAL hay
DRIVER_IRQL_NOT_LESS_OR_EQUAL), nhng t nht bn s tm ra rng bn c
mt vn .

Nu bn kim tra trnh iu khin ca bn trong mt tnh hnh trong cc trang c


cha DispatchPower s xy ra fortuitously c trong b nh, tuy nhin, s khng c
mt trang li. PAGED_CODE s pht hin ngay c vn nh vy

Ci t cc Driver Verifier "IRQL lc lng kim tra" la chn s lm tng ng k


c hi khm ph ra rng bn tan v cc quy nh v paging v IRQL. Ty chn lc
lng pageable trang ra khi bt c khi no xc nhn trnh iu khin b nh nng cao
IRQL DISPATCH_LEVEL hay ngoi.

Bin-Thi gian kim sot ca Pageability

Cho rng mt s phn ca trnh iu khin ca bn phi lun lun c c dn v mt


s phn c th c paged, bn cn mt cch kim sot cc giao ca bn v m d
liu vo paged v nonpaged pool. Bn php phn ca cng vic ny bng cch hng
dn lm th no bin apportion m ca bn v d liu khc nhau gia cc phn

The run-ti thi gian s dng tn ca cc phn a phn ca trnh iu khin ca bn


trong nhng ni bn c . Bn cng c th php phn ca cng vic ny ti thi gian
chy bng cch gi cc b nh Trng i din thi quen m ti s tho lun trong phn
k tip.

Ch :

Win32 executable file, bao gm c ht nhn-ch iu khin, ang c ni b thnh t


mt hay nhiu phn. Mt phn c th cha d liu v m hay, ni chung, c thm thuc
tnh nh l ang c c, ghi, shareable, thi hanh, v nh vy trn. Mt phn nh cng
l n v m bn c th ch khi bn xc nh kh nng trang

Khi driver ti mt hnh nh, h thng nhn phn ch c tn bt u vi Trang hay.


Eda (bt u. EDATA) vo paged pool, tr khi DisablePagingExecutive gi tr trong
HKLM \ System \ CurrentControlSet \ Control \ Session Manager \ Memory Qun l
ch cht s xy ra c thit lp (trong c trng hp khng c bng driver paging
xy ra).

). Lu rng cc tn ny l trng hp nhy cm! Trong mt trong nhng twists t


c nh hng n s phn ca chng ti tt c theo thi gian, chy mm-Ice / W trn
Windows XP yu cu bn v hiu ha ht nhn trong paging bng cch ny. iu ny

61/369
chc chn lm cho kh hn tm thy li gy ra bi misplacement ca driver hoc m
d liu vo paged pool! Nu bn s dng debugger ny, ti khuyn bn nn religiously
s dng PAGED_CODE v m v Driver Verifier.

Cch truyn thng cho cc bin a m vo mt phn l s dng nhng alloc_text


pragma. K t mi bin s khng nht thit phi h tr cc pragma, cc DDK tiu
hoc xc nh hay khng xc nh vic ALLOC_PRAGMA cho bit nn s dng
pragma. Sau bn c th gi cc pragma xc nh v tr ca phn subroutines c
nhn ca bn trong trnh iu khin, nh sau:

#ifdef ALLOC_PRAGMA

#pragma alloc_text(PAGE, AddDevice)

#pragma alloc_text(PAGE, DispatchPnp)

#endif

Nhng ti liu phc v cho cc ni AddDevice v DispatchPnp hm vo paged pool.


Ca Microsoft C / C + + bin ni hai gy phin nhiu hn ch v vic s dng cc
alloc_text:

Cc pragma phi lm theo cc cng b ca mt hm nhng vic nh ngha. Mt cch


phi tun theo cc quy nh ny l tuyn b tt c cc hm trong trnh iu khin
ca bn trong mt tiu chun tiu tp tin v gi alloc_text ti u ca cc tp tin
ngun c cha mt hm nhng sau khi bn bao gm cc tiu .

Cc pragma ch c th c s dng vi hm c lin kt C-. Ni cch khc, n s


khng lm vic cho cc thnh vin lp hc hoc hm cho cc hm trong mt C + + m
ngun tp tin m bn khng khai bo bng cch s dng extern "C". kim sot
cc v tr ca cc bin d liu, bn s dng mt pragma khc nhau di s kim sot
ca l mt biu tng khc nhau preprocessor v m:

#ifdef ALLOC_DATA_PRAGMA

#pragma data_seg("PAGEDATA")

#endif

Data_seg pragma nguyn nhn ca tt c cc d liu tnh tuyn b cc bin trong mt


m-un ngun sau khi xut hin ca pragma i vo paged pool. Bn s nhn thy
rng ny pragma khc trong mt cch cn bn t alloc_text. Mt phn pageable bt u,
ni # pragma data_seg ( "PAGEDATA") xut hin v kt thc, ni mt countervailing
# pragma data_seg () xut hin. Alloc_text, mt khc, p dng cho mt hm c th.

62/369
Khi-Thi gian kim sot ca Pageability

Bng 3-3 lit k cc dch v, bn c th s dng hm chy thi gian tinh chnh s
pageability ca bn driver trong tnh hung khc nhau. Mc ch ca cc thi quen l
cho bn pht hnh ca b nh vt l m c khc c gn ln do m ca bn v d liu
trong sut thi gian khi n s khng c cn thit.

Trong Chng 8, v d, ti s tho lun lm th no bn c th t in thoi ca bn


vo mt t quyn lc nh nc trong thi gian khng hot ng. Powering xung c th
s c mt thi gian tt pht hnh cc trang web ca bn b kha

Ti ang i m t mt cch s dng cc hm kim sot pageability ca m trong


trnh iu khin ca bn. Bn c th mun c DDK m t tm hiu v nhng cch
khc s dng chng. Subroutines trong phn phi u tin ca bn driver vo mt
cch ring bit, tn m phn, nh th ny:

#pragma alloc_text(PAGEIDLE, DispatchRead)

#pragma alloc_text(PAGEIDLE, DispatchWrite)

l, xc nh mt phn tn bt u vi Trang v kt thc bng bt c bn k t suffix


bn vui lng. Sau , s dng alloc_text pragma t mt s nhm cc thi quen ca
ring bn trong phn c bit. Bn c th c bao nhiu phn pageable c bit nh
bn mun, nhng vn hu ca bn s pht trin nh bn driver ca bn chia theo cch
ny. Trong thi gian s khi (ni rng, trong DriverEntry), kha ca bn pageable phn
nh th ny:

PVOID hPageIdleSection;

NTSTATUS DriverEntry(...)

63/369
{

hPageIdleSection = MmLockPagableCodeSection((PVOID)

DispatchRead);

Khi bn gi MmLockPagableCodeSection, bn ch nh bt k tt c cc a ch trong


phn bn ang c gng kha. Thc s nhm mc ch thc hin cuc gi trong thi
gian ny DriverEntry c x l c c gi tr ca n tr v, ti hin th m bn
tit kim trong ton cu mt bin tn hPageIdleSection. Bn s s dng nhiu x l sau
ny, khi bn quyt nh bn khng cn mt phn trong b nh cho mt trong khi:

MmUnlockPagableImageSection(hPageIdleSection);

iu ny s m kha gi cc trang web c cha cc PAGEIDLE phn v cho php h


di chuyn ra v vo b nh theo yu cu. Nu bn sau ny khm ph rng bn cn
nhng trang li mt ln na, bn thc hin cuc gi ny:

MmLockPagableSectionByHandle(hPageIdleSection);

Sau y gi ny, cc PAGEIDLE phn s li mt ln na c nonpaged trong b nh


(nhng khng nht thit phi l cng mt vt l b nh nh trc ). Lu rng hm
ny gi l c sn cho bn ch trong Windows 2000 v Windows XP, v sau ch nu
bn bao gm ntddk.h thay v wdm.h. Trong nhng tnh hung khc, bn s phi gi
li MmLockPagableCodeSection

Bn c th lm g tng t t d liu vo cc i tng pageable phn

PVOID hPageDataSection;

#pragma data_seg("PAGE")

ULONG ulSomething;

#pragma data_seg()

hPageDataSection = MmLockPagableDataSection((PVOID)

&ulSomething);

MmUnlockPagableImageSection(hPageDataSection);

64/369
MmLockPagableSectionByHandle(hPageDataSection);

Ti pht nhanh v loose vi c php ca ti y-nhng ti liu s xut hin trong


rng ri b tch phn ca trnh iu khin ca bn. Nhng tng ng sau nhng dch
v hm qun l b nh ti ch cn c m t l bn s bc u kha mt phn c cha
mt hoc nhiu trang web v c c mt x l cho s dng trong cc cuc gi.Bottom
of Form

Sau bn c th m kha cc trang trong mt phn bng cch gi in thoi qua


MmUnlockPagableImageSection v x l tng ng. Relocking phn sau ny i hi
mt cuc gi n MmLockPagableSectionByHandle.

A nhanh chng tt hin c sn nu bn chc chn rng khng c phn ca driver ca


bn s cn phi c cho c dn trong mt thi gian. MmPageEntireDriver s nh du
tt c cc phn trong mt hnh nh nh bng driver ang c pageable. Ngc li,
MmResetDriverPaging s khi phc li cc bin-thi gian pageability thuc tnh cho
ton b trnh iu khin. gi nhng thi quen, bn ch cn a ch ca mt s on
m hoc d liu trong trnh iu khin. V d:

MmPageEntireDriver((PVOID) DriverEntry);

MmResetDriverPaging((PVOID) DriverEntry);

Bottom of Form

V d:

#define DRIVERTAG ''KNUJ''

PVOID p = ExAllocatePoolWithTag(PagedPool, 42, DRIVERTAG);

Handling Low-Memory Situations

Nu khng c b nh p ng yu cu ca bn, cc allocator pool s em li mt


NULL tr. Bn nn lun lun kim tra li gi tr v lm ci g hp l. V d:

PMYSTUFF p = (PMYSTUFF) ExAllocatePool(PagedPool, sizeof(MYSTUFF));

if (!p)

return STATUS_INSUFFICIENT_RESOURCES;

Cc loi pool bao gm khi nim phi thnh cng. Nu khng c b nh heap
satisify mt yu cu t phi-pool thnh cng, h thng kim tra li. Trnh iu khin

65/369
khng nn phn b b nh bng cch s dng mt trong nhng thnh cng phi-
specifiers. iu ny l do mt driver c th gn nh lun lun tht bi no l hot ng
theo cch

Gy ra mt h thng sp trong mt b nh thp-tnh hnh khng phi l ci g lm


nn mt driver. Hn na, ch c mt gii hn pool phi-thnh cng ca b nh tn ti
trong ton b h thng, v h iu hnh c th khng c kh nng phn b b nh cn
thit c th gi cho cc my tnh chy nu trnh iu khin ln mt s.

Nu bn HOC gi tr POOL_RAISE_IF_ALLOCATION_FAILURE (0x00000010)


vo pool loi m, cc heap allocator s tng mt
STATUS_INSUFFICIENT_RESOURCES ngoi tr thay v tr v NULL nu khng c
b nh. Bn nn s dng mt cu trc ngoi tr khung nm bt nh mt ngoi l.
V d:

#ifndef POOL_RAISE_IF_ALLOCATION_FAILURE

#define POOL_RAISE_IF_ALLOCATION_FAILURE 16

#endif

#define PagedPoolRaiseException (POOL_TYPE) \

(PagedPool POOL_RAISE_IF_ALLOCATION_FAILURE)

#define NonPagedPoolRaiseException (POOL_TYPE) \

(NonPagedPool POOL_RAISE_IF_ALLOCATION_FAILURE)

NTSTATUS SomeFunction()

NTSTATUS status;

__try

PMYSTUFF p = (PMYSTUFF)

ExAllocatePoolWithTag(PagedPoolRaiseException,

sizeof(MYSTUFF), DRIVERTAG);

66/369
<Code that uses "p" without checking it for NULL>

status = STATUS_SUCCESS;

__except(EXCEPTION_EXECUTE_HANDLER)

status = GetExceptionCode();

return status;

NOTE POOL_RAISE_IF_ALLOCATION_FAILURE c nh ngha trong


NTIFS.H, mt phn u tp tin l c sn ch l mt phn ca thm chi ph ci tp H
thng kit. Lm b nh phn vi c ny c thit lp ph bin trong h thng tp tin
trnh iu khin, tuy nhin, ti ngh rng bn nn bit v iu .

Incidentally, ti ngh bn khng i crazy c gng chn on hoc phc hi t tht


bi b tr nh, khi b nh. Nh l mt vn thc t, mt phn b cho cc yu cu,
ni rng, 32 byte l khng bao gi i n tht bi. Nu b nh thng l nhng mt, h
thng s c chy nh vy sluggishly chc rng ai s khi ng li my

Bn phi khng phi l nguyn nhn ca mt h thng sp trong tnh hnh ny, tuy
nhin, v bn do s c cc ngun tim nng ca mt t chi-ca-dch v khai thc.

Nhng t khi c li s khng pht sinh trong thc t i sng, khng c im trong xy
dng a vo m ca bn ng nhp li trnh iu khin, tn hiu WMI cc s kin,
in g li tin nhn, thc hin cc thut ton thay th, v nh vy trn. Tht vy, thm m
cn thit lm tt c m c th l l do h thng khng c thm 32 byte cung cp
cho bn l ngi u tin ni! V vy, ti khuyn bn nn kim tra cc gi tr tr ra tt
c cc cuc gi n t ExAllocatePoolWithTag.

Nu n discloses mt li, lm bt c yu cu v s tr li mt m trng thi. Khong


thi gian.

67/369
b nh (Releasing a Memory Block)

gii phng b nh c bn cp pht trc vi ExAllocatePoolWithTag, bn gi


ExFreePool.

ExFreePool((PVOID) p);

Bn cn gi nhng rnh ghi cha c xc nh ca b nh m bn c , c cp pht


trc t b nh chung gii phng n khi n khng cn cn. Khng ai khc s lm
iu cho bn. Thnh thong bn phi c ti liu DDK ca nhng hm bn gi vi
mt ci nhn v quyn s hu b nh. Chng hn, trong hm AddDevice ti cho thy n
trong chng trc , n c gi ti IoRegisterDeviceInterface. Hm c mt
tc dng ph: n cp pht mt khi b nh cha chui c tn l giao din(interface).
Bn s phi gii phng b nh sau ny. Thit b kim chng s kim tra thi gian
DriverUnload m bo gii phng tt c b nh n cp pht . Ngoi ra, vic kim
tra din ra ng n thit b kim chng u gi ti ExFreePool chc chn rng h
tham chiu ti tt c b nh c cp pht t mt vng nht nh vi IRQL hin hnh .
Phn u DDK khai bo mt hm undocumented c tn ExFreePoolWithTag. Hm ny
c d nh s s dng ni b lm chc chn nhng thnh phn h thng khng
c gii phng b nh thuc v nhng thnh phn khc . Hm tht s c gi l
mt " tiu ph ca thi gian " bi mt trong nhng ngi pht trin Microsoft, m kh
nhiu ngi ni rng chng ti khng cn lo lng phi lm n hay s dng n nh th
no. (Gi : bn cn lm mt s th undocumented khc s dng n mt cch thnh
cng.)

Nhng i sl tng t nh chng ti ang c hc tr nhng ci bn cung cp thm


u tin ch bo. Nhn Bng 3-5.

DDK cho bit rng a s nhng thit b iu khin cn phi ch r NormalPoolPriority


khi gi n hm ny. HighPoolPriorityshould c dnh ring cho nhng trng thi m
s thnh cng l nguy kch quan trng i vi s hot ng lin tc ca h thng. Bn
c th b xung bng mnh SpecialPoolOverrun v SpecialPoolUnderrun vo trong
Bng 3-5 ( chng hn,LowPoolPrioritySpecialPoolOverrun, vn vn). Nu mt s cp
pht s dng vng c bit, c trn v nhng c underrun b ghi mt cch mc nh

68/369
. Lc ti vit iu ny,ExAllocatePoolWithTagPriority bin chuyn v tr ln n
gin c gi l ExAllocatePoolWithTag nu bn yu cu c nh s trang b nh
mc u tin c bit hay bt k quyn u tin no. Vic kim tra thm ti nguyn ch
xy ra vi nhng yu cu nh s trang b nh c quyn u tin thp hay bnh thng.
Hnh vi ny c th thay i trong nhng gi dch v hay nhng phin bn sau ca h
iu hnh.

Pseudofunction sau y minh ha thao tc nh th no danh sch n lin kt

typedef struct _ONEWAY {

SINGLE_LIST_ENTRY linkfield;

} ONEWAY, *PONEWAY;

69/369
SINGLE_LIST_ENTRY SingleHead;

SingleHead.Next = NULL;

PONEWAY psElement = (PONEWAY) ExAllocatePool(PagedPool,

sizeof(ONEWAY));

PushEntryList(&SingleHead, &psElement->linkfield);

SINGLE_LIST_ENTRY psLink = PopEntryList(&SingleHead);

if (psLink)

psElement = CONTAINING_RECORD(psLink, ONEWAY, linkfield);

ExFreePool(psElement);

1. Thay v vic ko theo mt hm dch v vn hnh khi to phn u danh sch lin
kt n, ch thit lp trng k tip hng ti NULL.. Ch s thiu vng ca mt hm
dch v cho vic th nghim liu danh sch ny trng rng; ch kim tra chnh phn t
k tip PushEntryList t mt phn t ti u ca danh sch, m n l phn duy nht ca
danh sch c th trc tip tip cn

2. PushEntryList nhn mt yu t ti cc u trong danh sch, ch l mt phn ca


danh sch l c th truy cp trc tip. Thng bo m bn ch nh a ch ca nhng
thay v cc lnh vc lin kt ring ca bn ONEWAY c cu.

3. PopEntryList loi b nhng mc u tin trong danh sch v s mang li cho bn mt


tr li cc lnh vc lin kt bn trong n. Ngc li vi danh sch lin kt-gp i,
mt gi tr NULL cho thy rng trong danh sch l khng c sn phm no. Trong thc
t, khng c nc IsListEmpty s dng vi mt danh sch lin kt-singly.

Lookaside Lists

Thm ch tt nht c th s dng cc thut ton, mt ngi qun l heap ngu nhin m
chng ti kinh doanh vi kch c khi b nh s yu cu mt s him thi gian x l
coalesce lin k min ph t cc khi thi gian. Hnh 3-10 minh ho nh th no, ci g
khi tr v khi B vo heap ti mt thi gian khi khi A v C v ang min ph, cc
heap qun l c th kt hp khi A, B, v C to thnh mt khi duy ln

70/369
Cc khi ln, sau s c sn p ng mt s yu cu sau cho mt khi ln hn bt
k mt trong ba thnh phn gc

Hnh 3-10. Coalescing adjacent free blocks in a heap.

Nu bn bit bn lun lun c c lm vic vi kch thc c nh-khi b nh, bn


c th th cng mt cch hiu qu hn nhiu chng trnh qun l mt heap. Bn c
th, v d, preallocate mt khi ln b nh rng bn chia thnh tng phn cho cc kch
thc c nh. Sau , bn c th devise mt s chng trnh cho bit khi l min
ph v c s dng trong, nh ngh do Hnh 3-11.

li mt khi nh mt heap ch bao gm vic nh du n nh min ph-bn khng


cn phi coalesce n lin k vi khi bi v bn khng bao gi cn phi ngu nhin
kch thc p ng yu cu.

Hnh 3-11. A-heap cha c nh kch c khi.

Hnh 3-12 minh ho khi nim ca mt lookaside danh sch. Hy tng tng rng bn
c mt ly m bn c th (no -php lut ca Vt l khng chnh xc lm cho vic
ny d dng!) S d ngay thng, trong mt h pool

Bottom of Form

71/369
H thng nh k iu chnh su ca tt c cc lookaside danh sch da trn thc t s
dng. Cc chi tit ca cc thut ton khng tht s quan trng, v chng ti c th thay
i trong bt k trng hp no. V c bn (trong bn pht hnh hin ti, anyway), h
thng s gim chiu su ca lookaside danh sch m khng c c truy cp trong thi
gian gn y hay khng c truy cp pool buc t nht 5 phn trm ca thi gian. Su
khng bao gi i di y 4, tuy nhin, cng l chiu su ban u ca mt danh sch
mi.

Bng 3-8 lit k cc dch v tm hm m bn s dng khi bn lm vic vi mt


lookaside danh sch. C tht s hai b bn hm, mt t cho mt danh sch lookaside
rng paged qun l b nh (cc ExXxxPagedLookasideList t) v mt cho mt
danh sch lookaside rng nonpaged qun l b nh (ExXxxNPagedLookasideList cc
thit lp). iu u tin bn phi lm l t nonpaged b nh cho mt
PAGED_LOOKASIDE_LIST hoc mt i tng NPAGED_LOOKASIDE_LIST

Ngay c cc paged nhiu i tng cn phi c nonpaged trong b nh v h thng s


truy cp vo danh sch i tng chnh n ti mt cao IRQL.

Blocksize cc tham s l kch c ca khi b nh bn s c phn b t danh sch, v


t kha l 32-bit, gi tr t kha bn mun t pha trc ca mi khi nh vy. Hai
i s khng c placeholders cho cc gi tr m bn cung cp trong phin bn trc
ca Windows NT, nhng m by gi xc nh trn h thng ring ca mnh; nhng gi
tr u c c kim sot loi phn b v su ca lookaside danh sch.

b tr mt b nh khi t danh sch, gi in cho ph hp AllocateFrom hm:

PVOID p = ExAllocateFromPagedLookasideList(pagedlist);

PVOID q = ExAllocateFromNPagedLookasideList(nonpagedlist);

72/369
To put a block back onto the list, call the appropriate FreeTo function:

ExFreeToPagedLookasideList(pagedlist, p);

ExFreeToNPagedLookasideList(nonpagedlist, q);

Finally, to destroy a list, call the appropriate Delete function:

ExDeletePagedLookasidelist(pagedlist);

ExDeleteNPagedLookasideList(nonpagedlist);

Nu bn thc hin li ny, trong thi gian ti cc h thng chy qua, mt lot cc danh
sch cc lookaside iu chnh cc danh sch ca h su, n s t chn xung ti ch,
ni i tng danh sch ca bn c s dng c, c l vi kt qu xu.

73/369
Trnh by chui (String Handling)
WDM trnh iu khin c th lm vic vi cc d liu trong bt k phn no trong bn
nh dng:

Mt chui Unicode, thng c m t bi mt c cu UNICODE_STRING, cha


16-bit k t. M unicode c im thch ng vi ngn ng script c s dng
trn hnh tinh ny. A whimsical c gng c chun ha m s im thng cho cc
Klingon ngn ng, trong bo co trong n bn u tin, b t chi. Mt ngi c n
bn u tin ca ti sau y c gi e-mail bnh lun v vic ny:

74/369
K thut lp trnh hn hp (Miscellaneous Programming
Techniques )
Truy cp vo Registry

Windows XP v Windows 98/Me ghi li cu hnh v cc thng tin quan trng trong mt
c s d liu gi l ng k. WDM trnh iu khin c th gi cc chc nng c lit
k trong bng 3-10 truy cp cc ng k. Nu bn thc hin ch ngi dng
truy cp chng trnh lin quan n ng k, bn c th c th on nh th no s
dng cc chc nng trong mt driver. Ti c tm thy ht nhn-ch h tr y
cc chc nng khc nhau, tuy nhin, ti ngh rng gi tr ca n m t cch no bn c
th s dng chng.

Trong phn ny, ti s tho lun, trong s nhng th khc, cc gia nh ca ZwXxx
thi quen v RtlDeleteRegistryValue, m cung cp cc chc nng c bn ng k rng
suffices cho hu ht cc trnh iu khin WDM.

75/369
M ra mt registry key

Trc khi bn c th interrogate gi tr trong vic ng k, bn cn phi m cc kho


c cha chng. Bn s dng vo ZwOpenKey m mt cha kha hin ti. ZwCreateKey
bn s dng m hoc mt trng im hin ti hoc to ra mt kho mi. Hoc
chc nng cn thit bn u tin khi to mt OBJECT_ATTRIBUTES c cu vi tn
ca ch cht v (c l) cc thng tin khc. OBJECT_ATTRIBUTES cc cu trc
cng b sau y:

typedef struct _OBJECT_ATTRIBUTES {

ULONG Length;

HANDLE RootDirectory;

PUNICODE_STRING ObjectName;

ULONG Attributes;

PVOID SecurityDescriptor;

PVOID SecurityQualityOfService;

} OBJECT_ATTRIBUTES;

Hn l khi to mt d ca cu trc ny bng tay, n d s dng


InitializeObjectAttributes v m, m ti tin v bn hin th.

Gi, v d, rng chng ti mun m cc dch v ch cht cho cc driver ca chng


ti. The I / O Trng i din cho chng ti tn ca kho ny nh l mt tham s
DriverEntry. V vy, chng ti c th vit m nh sau:

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,

PUNICODE_STRING RegistryPath)

OBJECT_ATTRIBUTES oa;

InitializeObjectAttributes(&oa, RegistryPath, OBJ_KERNEL_HANDLE

OBJ_CASE_INSENSITIVE, NULL, NULL);

76/369
HANDLE hkey;

status = ZwOpenKey(&hkey, KEY_READ, &oa);

if (NT_SUCCESS(status))

ZwClose(hkey);

1. Chng ti ang bt u cc i tng thuc tnh c cu pathname ng k vi chng


ti bng cch cung cp cho cc I / O Trng i din v bo mt vi mt NULL
descriptor. ZwOpenKey s b qua cc an ninh descriptor anyway-bn c th xc nh
thuc tnh bo mt ch khi bn to mt cha kha cho ln u tin.

2. ZwOpenKey s m kho cho c v lu tr cc kt qu x l ca chng ti trong


hkey bin.

3. ZwClose l mt thi quen chung cho ng mt x l mt ht nhn-ch i


tng. y, chng ti s dng n ng trnh x l chng ti ng k vo cha
kha.

Cc OBJ_KERNEL_HANDLE c, hin th trong mu m trc, l rt quan trng cho


cc h thng tch hp. Nu bn ang chy trong bi cnh ca mt ngi dng si khi
bn gi ZwOpenKey, v nu bn khng cung cp ny bit, c, cc bn s c c x l
s c sn sng cho ngi s dng ch x l. N thm ch c th xy ra rng ngi
s dng ch -m s ng trnh x l mi v m ra mt i tng, li nhn c cng
mt s gi tr. All of a sudden, cc cuc gi ca bn ng k chc nng s c giao
dch vi cc sai loi x l. Nhng cch khc m registry phm

Ngoi ra vo ZwOpenKey, Windows XP cung cp hai chc nng cho cc phm m ng


k.

IoOpenDeviceRegistryKey cho php bn m mt trong nhng phm c bit ng k


lin kt vi mt i tng in thoi:

HANDLE hkey;

Status = IoOpenDeviceRegistryKey(pdo, flag, access, &hkey);

77/369
ni pdo l a ch ca cc i tng vt l in thoi (PDO) di cng ca trnh iu
khin c bit ca bn stack, c l mt ch cho cc kho c bit m bn mun m (xem
B ng 3-11), v truy cp l mt v d nh mt n truy cp KEY_READ

Ti s dng IoOpenDeviceRegistryKey vi PLUGPLAY_REGKEY_DEVICE c rt


thng xuyn trong cc trnh iu khin ca ring ti. Trong Windows XP, chc nng
ny s m ra nhng thit b subkey Cc thng s ca phn cng, cha kha cho in
thoi. Trong Windows 98/Me, n s m ra phn cng, cha kha ring ca mnh. Cc
phm c ng ni lu tr tham s thng tin v phn cng. Ti s tho lun ny
phm y chi tit trong Chng 15 trong kt ni vi cc ci t v phn phi mt
driver.

IoOpenDeviceInterfaceRegistryKey s m ra cc phm kt hp vi mt d ca mt thit


b giao din ng k:

HANDLE hkey;

status = IoOpenDeviceInterfaceRegistryKey(linkname, access,

&hkey);

ni linkname l lin kt tng trng tn ca ng k v truy cp vo giao din truy cp


l mt mt n nh KEY_READ.

Bt v ci t cc gi tr

Thng thng, bn m mt cha kha v ng k m bn mun, ly mt gi tr t c


s d liu. Cc chc nng c bn m bn s dng cho mc ch l ZwQueryValueKey.
V d, ly li gi tr trong imagePath bng driver dch v ch cht-Ti tht s khng
bit l do ti sao bn mun bit ny, nhng khng phi l b phn ca ti-bn c th
s dng cc m sau y:

UNICODE_STRING valname;

RtlInitUnicodeString(&valname, L"ImagePath");

78/369
size = 0;

status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation,

NULL, 0, &size);

if (status == STATUS_OBJECT_NAME_NOT_FOUND size == 0)

<handle error>;

size = min(size, PAGE_SIZE);

PKEY_VALUE_PARTIAL_INFORMATION vpip =

PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(PagedPool, size);

if (!vpip)

<handle error>;

status = ZwQueryValueKey(hkey, &valname, KeyValuePartialInformation,

vpip, size, &size);

if (!NT_SUCCESS(status))

<handle error>;

<do something with vpip->Data>ExFreePool(vpip);

y, chng ti thc hin hai cuc gi ZwQueryValueKey. Mc ch ca cuc gi


u tin l xc nh bao nhiu khng gian, chng ti cn phi phn b cho cc c cu
KEY_VALUE_PARTIAL_INFORMATION chng ti ang c gng ly. Th hai,
gi truy thng tin. Ti cn li kim tra cc li trong m ny fragment li v khng lm
vic trong thc t ra con ng cho chng ti mong i. c bit, ti on rng cc bc
u tin gi ZwQueryValueKey s tr li STATUS_BUFFER_TOO_SMALL (k t
khi ti qua n khng-mt chiu di m). N khng lm iu , mc d. Quan trng l
STATUS_OBJECT_NAME_NOT_FOUND m khng thnh cng, cho thy gi tr thc
s khng tn ti. V vy, ti kim tra cho rng ch c gi tr. Nu c mt s li khc
ngn cn ZwQueryValueKey t lm vic, cc cuc gi th hai s uncover n.

Ci c gi l "mt phn" thng tin trong c cu bn ly bng cch ny cha cc gi


tr ca d liu v mt m t v mt lot cc d liu dng:

79/369
typedef struct _KEY_VALUE_PARTIAL_INFORMATION {

ULONG TitleIndex;

ULONG Type;

ULONG DataLength;

UCHAR Data[1];

} KEY_VALUE_PARTIAL_INFORMATION,

*PKEY_VALUE_PARTIAL_INFORMATION;

Loi hnh l mt trong nhng loi d liu ng k lit k trong bng 3-12. (Cc loi d
liu l c th c nhng khng quan tm n trnh iu khin thit b.) DataLength l
chiu di ca d liu gi tr, v d liu l d liu ring ca mnh. TitleIndex khng c
lin quan n trnh iu khin. Di y l mt s d kin hu ch bit v cc loi
d liu khc nhau:

REG_DWORD l 32-bit unsigned integer nh dng no (v cui ln hay nh cui)


l nn tng cho t nhin.

REG_SZ m t mt null-Unicode chm dt chui gi tr. The Terminator null c


bao gm trong DataLength truy cp.

m rng mt REG_EXPAND_SZ c gi tr bng cch thay bin mi trng, qu


v nn RtlQueryRegistryValues nh ca bn s dng phng php hi cc ng k. Ni
b cho cc thi quen truy cp cc bin mi trng khng phi l ti liu hoc xc cho
s dng bi trnh iu khin.

RtlQueryRegistryValues cng l mt cch tt interrogate REG_MULTI_SZ gi tr


trong n s gi ca bn c xem thng gi mt ln cho mi phng trong s c
tim nng rt nhiu nhng dy.

Ch thch:

Mc d, r rng ch ca RtlQuery RegistryValues, ti c trnh bng cch s


dng n bao gi ht, v n s gy ra v ng xe trong mt trong cc trnh iu khin ca
ti. Tt nhin, gi tr ti c cc chc nng cn thit gi gip mt chc nng
c t trong s khi phn ca ht nhn v c, do , hin nay khng cn.

80/369
thit lp mt gi tr ng k, bn phi c KEY_SET_VALUE truy cp vo cha m
cha kha. Ti s dng KEY_READ sm hn, s khng cho bn truy cp nh
vy. Bn c th s dng KEY_WRITE hay KEY_ALL_ACCESS, mc d bn thu c
nhiu hn do cn thit cho php. Sau , gi ZwSetValueKey. V d:

RtlInitUnicodeString(&valname, L"TheAnswer");

ULONG value = 42;

ZwSetValueKey(hkey, &valname, 0, REG_DWORD, &value,

sizeof(value));

Subkeys xa hoc gi tr

xa mt gi tr trong mt cha kha m ra, bn c th s dng


RtlDeleteRegistryValue trong cch c bit sau y:

RtlDeleteRegistryValue(RTL_REGISTRY_HANDLE, (PCWSTR) hkey,

L"TheAnswer");

RtlDeleteRegistryValue ni chung l mt dch v c chc nng u tin i s c


th ch nh mt trong mt s ni c bit trong cc ng k. Khi bn s dng
RTL_REGISTRY_HANDLE, nh ti lm trong v d ny, bn ch ra rng bn c
mt m kho x l trong vng m bn mun xa mt gi tr. Bn ch r trng im
(vi mt nm bin lm cho hnh phc) nh l i s th hai. Th ba, v cui cng l
i s-null chm dt Unicode tn ca gi tr m bn mun xa. y l mt trong nhng
thi gian khi bn khng c to ra mt c cu UNICODE_STRING m t chui.

81/369
Trong Windows 2000 v sau ny, bn c th s dng ZwDeleteValueKey xa mt
gi tr (n l mt gim st rng chc nng ny khng phi l ti liu trong DDK):

UNICODE_STRING valname;

RtlInitUnicodeString(&valname, L"TheAnswer");

RtlDeleteValueKey(hkey, &valname);

Bn c th xo ch nhng phm m bn m ra vi t nht l cho php XO (m bn


nhn c vi KEY_ALL_ACCESS). Gi ZwDeleteKey bn:

ZwDeleteKey(hkey);

Cha kha cho n khi cuc sng trn tt c cc x l ang ng ca, nhng cc n lc
m mt ca hng mi x l cc phm hoc truy cp vo cc phm bng cch s
dng bt c hin ang m x l s khng thnh cng vi STATUS_KEY_DELETED.
K t khi bn c mt m x l ti im ny, bn cn phi chc chn s c gi
ZwClose sometime. (The DDK ti liu hng dn cho cc mc nhp ZwDeleteKey ni
nhng x l s tr thnh khng hp l. It doesnt-bn vn phi ng n bng cch gi
in thoi ZwClose.)

Enumerating Subkeys hoc cc gi tr

Mt hot ng phc tp, bn c th thc hin vi mt k m l cha kha enumerate


cc yu t (subkeys v gi tr) m c cha cha kha. lm c iu ny, bn s
thy u tin gi ZwQueryKey xc nh mt vi thc t v cc subkeys v cc gi
tr, chng hn nh s in thoi ca ngi, di ca tn ln nht, v nh vy trn.
ZwQueryKey c mt i s cho bit rng ca ba loi thng tin bn mun ti v cc
phm. Cc loi c t tn c bn, node, v y . chun b cho mt Enumeration,
bn mun c quan tm u tin trong y thng tin:

typedef struct _KEY_FULL_INFORMATION {

LARGE_INTEGER LastWriteTime;

ULONG TitleIndex;

ULONG ClassOffset;

ULONG ClassLength;

ULONG SubKeys;

82/369
ULONG MaxNameLen;

ULONG MaxClassLen;

ULONG Values;

ULONG MaxValueNameLen;

ULONG MaxValueDataLen;

WCHAR Class[1];

} KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION;

y thc s l c cu ca bin chiu di t Lp [0] ch l nhng k t u tin ca tn


lp hc. It's phong tc thc hin mt cuc gi tm hiu cch thc ln, mt buffer
bn cn phi phn b v mt cuc gi th hai c c nhng d liu, nh sau:

ULONG size;

ZwQueryKey(hkey, KeyFullInformation, NULL, 0, &size);

size = min(size, PAGE_SIZE);

PKEY_FULL_INFORMATION fip = (PKEY_FULL_INFORMATION)

ExAllocatePool(PagedPool, size);

ZwQueryKey(hkey, KeyFullInformation, fip, size, &size);

By gi bn c quan tm trong subkeys ng ky ca bn, bn c th thc hin


trong vng lp sau y gi ZwEnumerateKey:

for (ULONG i = 0; i < fip->SubKeys; ++i)

ZwEnumerateKey(hkey, i, KeyBasicInformation, NULL, 0, &size);

size = min(size, PAGE_SIZE);

PKEY_BASIC_INFORMATION bip = (PKEY_BASIC_INFORMATION)

ExAllocatePool(PagedPool, size);

83/369
ZwEnumerateKey(hkey, i, KeyBasicInformation, bip, size, &size);

<do something with bip->Name>

ExFreePool(bip);

Cha kha thc t, bn khm ph v mi subkey l tn ca n, m cho thy tnh ln nh


l mt chui Unicode trong c cu KEY_BASIC_INFORMATION bn ly bn trong
vng lp:

typedef struct _KEY_BASIC_INFORMATION {

LARGE_INTEGER LastWriteTime;

ULONG Type;

ULONG NameLength;

WCHAR Name[1];

} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION

Khng phi l tn null-chm dt, bn phi s dng cc NameLength thnh thnh vin
ca cc c cu xc nh chiu di ca n. ng qun rng trong chiu di l byte!
Tn l khng y hoc ng dn ng k; iu ch cn tn ca subkey no trong
vng cha kha cha n. y tht s l may mn, bi v bn c th d dng m mt
subkey ca n cho mt tn v x l m cc bc cha m cha kha.

mt Enumeration ca cc gi tr trong mt khng gian m cha kha, nhn vin ca


cc phng php sau y:

ULONG maxlen = fip->MaxValueNameLen +

sizeof(KEY_VALUE_BASIC_INFORMATION);

maxlen = min(maxlen, PAGE_SIZE);

PKEY_VALUE_BASIC_INFORMATION vip = (PKEY_VALUE_BASIC_INFORMATION)

ExAllocatePool(PagedPool, maxlen);

for (ULONG i = 0; i < fip->Values; ++i)

84/369
{

ZwEnumerateValueKey(hkey, i, KeyValueBasicInformation, vip,

maxlen, &size);

<do something with vip->Name>

ExFreePool(vip);

Cp cho khng gian ln nht c th c cu trc


KEY_VALUE_BASIC_INFORMATION rng bn s lun lun ly
MaxValueNameLen da trn cc thnh vin ca KEY_FULL_INFORMATION c cu.
Bn trong vng trn, bn s thy mun lm ci g vi tn ca gi tr, m s n vi bn
nh l mt chui Unicode tnh trong cu trc ny:

typedef struct _KEY_VALUE_BASIC_INFORMATION {

ULONG TitleIndex;

ULONG Type;

ULONG NameLength;

WCHAR Name[1];

} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION;

Mt ln na, c tn ca mt gi tr v m x l cc ph huynh l cha kha ch cn


nhng g bn cn ly li gi tr, nh c hin th trong phn trc.

Hin c cc bin th trn ZwQueryKey v trn hai Enumeration chc nng m ti


khng c tho lun. Bn c th, v d, c c y thng tin v mt subkey khi
bn gi ZwEnumerateKey. Ti ch cho bn lm th no c c nhng thng tin c
bn bao gm cc tn. Bn c th ti d liu ch c gi tr, hoc tn cng vi d liu gi
tr, t ZwEnumerateValueKey. Ti ch cho bn lm th no c c tn ca mt gi
tr.

Truy cp tp tin

It's i khi hu ch c th c v vit thng xuyn a file t bn trong mt trnh


iu khin WDM. C l bn cn phi ti v mt s tin ln ca microcode vi phn

85/369
cng ca bn, hoc c l bn cn phi to ring ca bn rng ln ca thng tin ng
nhp cho mt s mc ch. C b ZwXxx thi quen gip bn lm c nhng iu
.

Kch truy cp thng qua cc thi quen ZwXxx yu cu bn chy c ti PAS


SIVE_LEVEL (xem chng k tip) trong mt si m c th an ton b treo. Trong
thc t, cc yu cu sau c ngha l bn phi khng c khuyt tt Asynchronous Th
tc cuc gi (APCs) bng cch gi in thoi KeEnterCriticalRegion. Bn s c trong
chng k tip rng mt s ng b ha primitives yu cu bn n IRQL nng cao
trn PASSIVE_LEVEL hay v hiu ho APCs. Gu ch cn ghi nh rng nhng
primitives v ng b ha tp tin khng tng ang truy cp.

M s mu

FILEIO cc mu trong trnh iu khin, phn ni dung minh ho cuc gi n mt s


trong cc chc nng ZwXxx tho lun trong phn ny. iu ny c bit l mu rt c
gi tr v n cung cp workarounds cho nn tng khng tng thich c cp phn
cui ca chng ny.

Hin ti m mt tp c, m mt tp tin hin c bn c th c n, hy lm


theo v d ny:

NTSTATUS status;

OBJECT_ATTRIBUTES oa;

IO_STATUS_BLOCK iostatus;

HANDLE hfile; // the output from this process

PUNICODE_STRING pathname; // you've been given this

InitializeObjectAttributes(&oa, pathname,

OBJ_CASE_INSENSITIVE OBJ_KERNEL_HANDLE, NULL, NULL);

status = ZwCreateFile(&hfile, GENERIC_READ, &oa, &iostatus,

NULL, 0, FILE_SHARE_READ, FILE_OPEN,

FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);

To hoc vit li mt tp

86/369
to mt tp tin mi, hoc m v truncate khng chiu di hin c mt tp tin,
thay th cc cuc gi n ZwCreateFile trong trc fragment ny vi mt trong:

status = ZwCreateFile(&hfile, GENERIC_WRITE, &oa, &iostatus,

NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,

FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);

Trong nhng fragments, chng ti thit lp mt c cu c OBJECT_ATTRIBUTES


Mc ch chnh l im n y pathname ca tp tin m chng ti ang v m.
Chng ti xc nh OBJ_CASE_INSENSITIVE thuc tnh bi v Win32 h thng tp
tin m hnh, khng c g khng cha tr nh trng hp ng k trong mt pathname.
Chng ti ch nh OBJ_KERNEL_HANDLE cho cng mt l do g chng ti lm
nh vy trong ng k v d hin th sm hn trong chng ny. Sau , chng ti gi
ZwCreateFile m cc x l.

Lnh vc x l

Mi phng trong qu trnh x l t nhn c mt bng m gn vi s x l cc i


tng n ht nhn. Khi bn m mt ZwCreateFile x l bng cch s dng, hoc
NtCreateFile, x l m thuc v cc quy trnh hin ti-sau , tr khi bn s dng
OBJ_KERNEL_HANDLE c. A-qu trnh x l c th s i, nu qu trnh chm dt.
Hn na, nu bn s dng cc x l trong mt bi cnh khc nhau qu trnh, bn s
c tham chiu gin tip no i tng (nu c) cho rng x l tng ng trong
qu trnh khc. Mt ht nhn x l, mt khc, c lu gi trong mt bng ton cu m
khng bin mt, khng c g cho n khi cc h iu hnh shuts xung v c th c
s dng m khng c bt k ambiguity trong qu trnh.

Nu bn c k hoch c ton b mt tp tin vo mt b nh m, bn s thy rt


c th mun ku gi cc ZwQueryInformationFile xc nh tng chiu di ca tp
tin:

FILE_STANDARD_INFORMATION si;

ZwQueryInformationFile(hfile, &iostatus, &si, sizeof(si),

FileStandardInformation);

ULONG length = si.EndOfFile.LowPart;

Thi gian hot ng ca tp tin

87/369
Bn s c kh nng mun c mt a tp tin trong mt WDM driver trong khi bn ang
bt u in thoi ca bn phn ng li mt IRP_MN_START_DEVICE yu cu.
(Xem Chng 6.) Ty thuc vo ni m in thoi ca bn t ng trong s khi trnh t,
bn c th hoc c th khng c quyn truy cp vo cc tp tin bng cch s dng nh
bnh thng pathnames \?? \ C: \ dir \ file.ext. c an ton, a cc tp tin d liu
ca bn vo mt s th mc di y ca h thng th mc gc v s dng nh mt file
\ SystemRoot \ dir \ file.ext. SystemRoot cc chi nhnh ca cc tn ny, lun lun c th
truy cp t cc h iu hnh c th c a file bt u ln.

Trong tt c cc trnh iu khin ca ti, ti xc nh l mt tn DRIVERNAME nh


th ny:

#define DRIVERNAME "xxx"

ni xxx l tn ca mt trnh iu khin thit b. Nh li rng thy hai gip bin string
constants nh l mt c nh. Trick c bit bng cch s dng ny cho php ti ct
v dn ton b subroutines, bao gm c cc cuc gi ca h KdPrint, t mt driver khc
m khng cn phi lm cho m ngun thay i.

Cc khng nh v m

Hu ch khc, kh nng g li k thut da trn v m khng nh:

ASSERT(1 + 1 == 2);

Trong khi kim tra xy dng driver ca bn, khng nh to ra m nh gi Boolean


biu hin. Nu cc biu hin l sai, khng nh s c gng ngn chn thc hin trong
debugger bn c th xem nhng g ang xy ra. Nu cc biu hin l ng, ca bn
tip tc thc hin chng trnh bnh thng. Debuggers ht nhn s tm dng khi xy ra
khng nh tht bi, ngay c trong xy dng nh bn l ca cc h iu hnh, nhn tin.

Quan trng kkng nh l mt tht bi trong mt bn l xy dng ca cc h iu hnh


m khng c ht nhn debugger chy to ra mt li kim tra.

Trnh iu khin Verifier

Cc Driver Verifier l mt phn ca kim tra v min ph xy dng ca cc h iu hnh


v l nhanh chng tr thnh mt trong nhng cng c chnh ca Microsoft cho trnh
iu khin kim tra cht lng. Bn c th khi chy Driver Verifier Bt u t Menu,
whereupon bn s c trnh by vi mt lot cc trang ca trnh wizard. y l mt t
ca mt con ng hng dn bn qua cc trang ny, ln u tin.

88/369
Hnh 3-14 minh ho vic ban u thut s trang. Ti khuyn bn nn kim tra cc To
chnh Ci t (i vi M s pht trin) la chn. iu ny s cho php bn la chn
xc nh chi tit Driver Verifier tu chn m bn mun tham gia.

Hnh 3-14. Driver Verifier thut s ban u trang

Sau khi thc hin cc ngh ca ti la chn t cc trang u tin, bn s c trnh


by vi mt trang th hai (xem Hnh 3-15). y, ti khuyn bn nn kim tra cc c
nhn Chn Ci t t A Danh sch y ty chn.

89/369
Hnh 3-15. Driver Verifier thut s th hai trang

Thut s trang k tip (xem Hnh 3-16) cho php bn ch nh cc ci t verifier bn


mong mun. c quy nh trong kim tra c thm vo mt s kim tra rng cc
Driver Verifier lm t ng.

90/369
Hnh 3-16. Driver Verifier ca thut s ci t tu chnh trang

Nhng la chn c sn ti thi im ti ang vit ny l nh sau:

Special l tt c cc lc lng b nh phn t trnh iu khin xc minh c lm


t nhng c bit pool. Nh c m t trong chng ny sm hn, nh vy phn c
t vo cui (hoc bt u) ca mt trang, v vy m sau khi lu tr (hoc trc khi) s
phn b b nh dn n mt li kim tra ngay lp tc.

Theo di cc nguyn nhn cc l Driver Verifier theo di b nh phn xc minh


c thc hin bi trnh iu khin. Bn c th xem s liu thng k v cch s dng
b nh nh n thay i theo thi gian. Cc Driver Verifier cng m bo rng tt c cc
phn c gii thot, khi xc minh unload trnh iu khin gip bn nm bt b nh
r.

IRQL lc lng kim tra nguyn nhn ch yu paged b nh c Flushed bt c


khi no mt xc nhn bng driver tng IRQL DISPATCH_LEVEL hoc trn. Hnh
ng ny gip tm nhng ni trnh iu khin thit b l khng chnh xc paged truy cp
b nh. Cc h thng chy kh chm khi ty chn ny c bt.

I / O M xc nhn nguyn nhn ca Driver Verifier kim tra vic thc hin c bn
nh th no l mt driver x l IRPs rng n to ra hoc forwards n cc trnh iu

91/369
khin. Enhanced I / O M xc nhn cc n lc tun ra driver ra li trong trng hp
ranh gii, chng hn nh hon tt v PnP Power IRPs khng chnh xc, lm cho cc gi
nh v trnh t, trong cc Trng i din PnP ti cc trnh iu khin, v nh vy
trn. Mt s trong nhng bi kim tra xy ra khi trnh iu khin thit b bt u bc
u, by the way, m c th ngn chn vic bt u t h thng.

Deadlock Detection to ra mt ca cc kha Hierarchy cho spin kha, mutexes,


v nhanh chng mutexes xc minh c s dng bi trnh iu khin pht hin tim
nng deadlocks. DMA Kim tra xc minh m bo rng trnh iu khin DMA thc
hin bng cch s dng phng php quy nh bi cc DDK.

Low Ti nguyn M phng ngu nhin khng bao gm vic phn pool t xc nhn
trnh iu khin, bt u by pht sau khi h thng bt u. Mc ch ca cc tht bi l
m bo rng trnh iu khin th nghim cc gi tr tr li t pool phn b cc cuc
gi.

Bn c th s dng mt th tc c bit, c m t trong cc DDK, kch hot kim


tra trn mt trnh iu khin SCSI miniport.

Ch thch:

C th c tng tc gia cc tu chn bn ch nh. Hin ti, thi gian, v d, yu cu


cho DMA kim tra pht hin deadlock hay r tt nng cao I / O xc minh.

Lu rng qu Driver Verifier l pht trin nhanh chng ngay c khi chng ti ni
chuyn. DDK c s t vn cho bn xy ra c lm vic vi cho up-to-date thng
tin. Sau khi bn chn tu chn verifier bn mun, bn s thy mt thut s cui cng ca
trang (xem Hnh 3-17). Trang ny cho php bn xc nh trnh iu khin m bn
mun xc minh bng cch kim tra cc hp trong mt danh sch. Sau khi thc hin l
la chn, bn s cn phi khi ng li my tnh, v nhiu ca Driver Verifier kim tra
yu cu khi ng-thi gian s khi. Khi ti g li mt trong cc trnh iu khin ca
ring ti, ti tm thy n thun tin nht ca ti khng c bng driver ti khi khi
ng li xy ra. Do vy, driver ca ti s khng c trong danh sch, v ti s c
thm n qua Thm vo Hin nay khng c ti Driver (s) To The Danh sch nt.

92/369
Hnh 3-17. iu khin la chn cho cc trang Driver Verifier. Driver Verifier tht bi
l li kim tra bng cch ny. Bn s cn phi c chy mt ht nhn hay debugger
phn tch cc bi cha, sau khi ng xe thc t isolate nguyn nhn ca tht bi.

93/369
Bi 7: THC HNH MT S BI TP
TRN VC++
Thc hnh mt s bi tp c bn trn Visual C++
Bi 1

Luyn tp VC++, hon thnh bi tp bui thc hnh trc

Bi 2

To 1 driver c bn, example.

94/369
Bi 8: LP TRNH GIAO TIP QUA
CNG LPT
Gii thiu cng LPT
a s cc my vi tnh u trao i thng tin thng qua cc ng sau y: Parallel port,
Serial port, USB v Network card. Parallel port l mt phn khng th thiu trong vic
s dng computer giao tip vi cc thit b in t khc. Bi ny ch yu dng cho
sinh vin hardware nhng vic hiu bit ca n cng khng tha i vi cc bn hc
software.

95/369
Cu trc cng LPT
Cu trc ca Parallel port nhn trn phng din hardware

Parallel port bao gm 25 pins (chn) c b tr theo s di y, a s giao din


u cm ca Parallel port u dng female:

8 pins dng gi v nhn data (t pin s 2 n s 9) gi l DATA Port (dn software


cng gi nh th). D liu trao i qua 8 pin ny c gi gn trong 1 byte.

5 pins dng hin th tnh trng hot ng ca parallel port: ang bn, ang gi/nhn
thng tin...(cc pin s 10-13 v pin s 15) gi l STATUS Port. D liu trao i qua 8
pin ny dng 5 bit cao ca byte.

4 pins dng iu khin gi l CONTROL Port, l cc pin s 1, 14, 16 v 17. D trao


i qua pnin ny dng 4 bit thp ca byte.

8 pins cn li c dng ty theo ngi s dng. Nu khng c s dng th chng


s c grounded (ni t-thut ng ngnh in?).

y l cu hnh c thng nht trong cng ngh vi tnh v c cng nhn bi IEEE
(vn l mt t chc ln nht v qui nh hardware quc t). Bn c th kim tra li cc
s pin v nh du bng cch nhn r hn vo cc dy parallel port cng nh parallel
port pha sau my vi tnh ca bn.

Vi v d cho hot ng ca parallel port

96/369
DATA port l ni thng tin s c trao i t computer n cc thit b khc (hai
chiu). Khi lp trnh t hn cng c khi bn nghe ni n chuyn vit 1 program/driver
cho cc hardware (nu bn lm cho mt s hng my in, vin thng...). y driver cho
parallel port chnh l chng trnh qun l v iu khin qu trnh trao i thng tin ny.
DATA port c 8 pins tc l 1 bytes. Bn c l tng nghe k thut ti thng tin qua ng
parallel port l nhanh nht (trong qu kh) nhng k thc n cng ch dng c 1byte =
8 bit = 8 ci pins ny m thi! Ti s tr li sau trong vic bn tho th no l mt si
dy parallel tt.

STATUS port l ni hin th cc qu trnh vn hnh ca parallel port. Mt v d n gin


l gi s bn mun in mt bi vit ra printer (d nhin l qua ng parallel port) nhng
khi nhn nt "print" th li thy my vi tnh hin th mt thng bo ht giy! Trn thc
t pha sau nhng hng ng ny l mt chui phi hp gia software v hardware. Khi
bn click "print" tc l bn kch hot mt trong nhng pins ca CONTROL port bng
software bo ci printer in bi ra. Nhng trc khi thc hin vic in printer cng t
bit n ht giy v t kch hot mt trong s nhng pins ca STATUS port bo cho
computer bit l ht giy. Kt qu l software iu khin qu trnh in kim tra (trc khi
in) thy c cho nn n hin thng bo ht giy cho bn. Nhiu hot ng tng t
nh printer cha on, printer ht mc, printer b kt giy...cng do phi hp gia nhng
ci pins ny m ra. Ti s bn k hn mc cu trc in sau ny.

Cu trc ca parallel port nhn trn phng din software

Thc ra th vi dn software, h cng khng cn bit pha parallel port sau lng my tnh
c bao nhin pin v mi pin cn bao nhiu in, cu trc nh th no...My ci ny hi
tha cho dn software! Tt c nhng g m mt ngi lp trnh cn bit l address ca
cc pin trn parallel port l ! 25 pins kia s c chia lm 3 phn vi tn gi l DATA
port (hay l DATA register), STATUS port (hay l STATUS register), v CONTROL
port (hay l CONTROL register). Mi port l 8 bits vi address hn hi. Nh m t t
u, DATA port s l 8 bits, STATUS port c 5 pins cho nn s cng thm 3 bit trng
to mt byte, tng t nh th cho CONTROL port. Ring phn a ch cho cc port ny
cng kh l phc tp, v n lin quan n BIOS. Nu bn hiu cch phn b memory
ca my tnh th n gin hn, cn khng th hy vng l li gii thch ca ti s lm bn
hiu phn no. i khi l khi my tnh bt ln (turn on) th BIOS s lm vic trc,
n s tm kim v nh a ch cho ci port trong my ca bn. V BIOS khng ci no
ging ci no cho nn li qui nh a ch ca n cng khc, tuy nhin di y l mt
v d in hnh (bn thng thy) trong cc my vi tnh ngy nay. Nhng a ch ny
bn c th thy khi khi ng my trong cc thng s BIOS hin ra.

Port Address Ghi ch 3BCh - 3BFh dng cho prallel port vn dnh vo Video Card (cch
c) 378h - 37Fh khu vc memory thng dng cho LPT 1 278h - 27Fh khu vc memory
thng dng cho LPT 2 ....

97/369
(nn nh l mi khon l 8 bits, tnh theo h hexadecimal)

Mt iu ti mun nhc cc bn l nhng thng tin a ra trn y thng l thay i


ty theo tng my tnh, mt my c th c nhiu LPT, thng thng th BIOS s d
xem trong my c bao nhiu port v s qui nh a ch cho tng port. Theo ti thng
thy th nu my bn c hai ci parallel port (nu bn mua motherboard c hai parallel
port) th LPT1 s c gn vo i ch 378h-37Fh (8 bits). Nu c LPT2 th s c gn
vo a ch 278h-27Fh. Ring phn 3BCh-3BFh trong qu kh thng c dng khi
parallel port ci sn trong video card. Nhng loi ny c ri, cho nn nhiu BIOS s
gn vo LPT1 cng khng chng. iu tt nht l bn vo BIOS kim tra l bit ngay
(life was not meant to be easy!).

Cng lu cc bn cc i ch trn l port address qui nh trn BIOS, khi BIOS qui
nh nhng a ch trn (tt my vn cn) n s qui nh km theo i ch lu thng tin
(tt my s mt) cho tng port. Nhng a ch di y s c dng a s bi cc bn
lp trnh kim tra x hin din ca parallel port trn my bn.

Start Address Function Software Identify 0000:0408h LPT1's Base Address

Base 0000:040Ah LPT2's Base Address

Base + 1 0000:040Ch LPT3's Base Address

Base + 2 0000:040Eh LPT4's Base Address (note 1)

Base + 3

Hy ly mt v d n gin v mt chng trnh kim tra v tr parallel port trn my


bn minh ho cho lp trnh iu khin parallel port di y:

#include <stdio.h>

#include <dos.h>

void main(void)

{/* Pointer to location of Port Addresses */

unsigned int far *ptraddr;

/* Address of Port */

unsigned int address;

98/369
int a;

ptraddr = (unsigned int far *)0x00000408;

for (a = 0; a < 3; a++)

{address = *ptraddr;

if (address == 0)

printf("No port found for LPT%d \n", a+1);

elseprintf("Address assigned to LPT%d is %Xh\n",

a+1, address);

*ptraddr++;}}

Chng trnh C ny n gin l tm n i ch 0000:0408h v d tm xem c port no


tn ti hay khng. N s d t 0000:0408h n 0000:040Dh kim tra LPT1, LPT2,
v LPT3. Bn nn nh mi base address s c 2 bytes (sizeof(unsigned int) = 2 bytes!).

Nh ti m t pha trn, Base+1, Base+2...chng qua l li gi ph thng trong cch lp


trnh. Chng hn bn kim tra nh s 10, 11, 12. Bn c th kim tra nh s 10 sau
nh s 10 +1 = 11 vn vn...

ng dng ca vic iu khin parallel port

Vic hiu hot ng v bit iu khin parallel port l ti cn thit cho cc bn i chuyn
su trong cc k ngh hardware. Hu ht cc dng c tn tin thi nay iu lin quan
n vic dng software vn hnh hardware, v d nh bn c th gi mt lnh t
my vi tnh lm cho tn la phng i, shutdown computer...iu thuc dng software
iu khin hardware. V vi trch nhim mt trnh iu khin n, bn phi thu hiu tt
c. Mt v d n gin khc trong iu khin hc nh iu khin robot, nu bn dng
software t my vi tnh kch hot mt pin no ca cng parallel v gi ti robot nh
mnh lnh, chng hn i ti pha trc, quay qua bn tri....

Cu trc o su bn trong ca Parallel port

Di y l lit k 25 chn ca parallel port vi tn gi (hardware v software) v th


t ca tng chn.

Chn tn signal (dng cho hardware)

99/369
Direction/type (nhn t PC)

Tn signal v th t ca bit (dng cho software)

Normal signal line function 1 -STROBE OC/Pullup Control register bit 0 kch hot
thng bo gi hoc nhn data, 0 l c, 1 l vit 2 D0 hai chiu Data register bit 0 bit 0
cha data 3 D1 hai chiu Data register bit 1 bit 1 cha data 4 D2 hai chiu Data register
bit 2 bit 2 cha data 5 D3 hai chiu Data register bit 3 bit 3 cha data 6 D4 hai chiu
Data register bit 4 bit 4 cha data 7 D5 hai chiu Data register bit 5 bit 5 cha data 8 D6
hai chiu Data register bit 6 bit 6 cha data 9 D7 hai chiu Data register bit 7 bit 7 cha
data 10 -ACK Input Status register bit 6 Pulsed low by printer to acknowledge data byte

Rising (usually) edge causes IRQ if enabled 11 BUSY Input Status register bit 7 kch
hot khi printer ang bn (busy) 12 NOPAPER Input Status register bit 5 kch hot khi
printer ht giy 13 SELECTED Input Status register bit 4 kch hot khi printer ang hot
ng 14 -AUTOFEED OC/Pullup Control register bit 1 kch hot thng bo data sn
sng c hoc vit 15 -ERROR Input Status register bit 3 kch hot khi printer b li
(v nhiu l do) 16 -INITIALIZE OC/Pullup Control register bit 2 kch hot printer
reset li v tr ban u 17 -SELECT OC/Pullup Control register bit 3 kch hot nh
du printer nhn c valid address 18 Ground ...Ground chn (18-25) b trng, dng
ty 25 Ground Thm mt hnh minh ho tng th hot ng ca parallel port.

100/369
101/369
Bi 9: THC HNH VI CC CHNG
TRNH GIAO TIP QUA CNG LPT
Thc hnh vi cc chng trnh giao tip qua cng LPT
Bi 1.

S dng VB6 thit lp, truyn d liu ra cng LPT v nhn d liu v

Bi 2.

M phng bt, tt LED khi s dng VB6 iu khin.

102/369
Bi 10: THC HNH VI CC CHNG
TRNH GIAO TIP QUA CNG COM
Gii thiu cng COM
IBM PC cung cp 2 cng ni tip: COM1 v COM2. Cc cng ny giao tip theo tiu
chun RS232. Chng c th c ni vi mt Modem dng cho mng in thoi,
hay ni trc tip vi mt my tnh khc. D liu c truyn qua cng ny theo cch
ni tip, ngha l d liu c gi i ni tip nhau trn 1 ng dy. Do cc d liu
c truyn i tng bit mt nn tc truyn chm, cc tc truyn c th l 300,
600, 1200, 2400, 4800bps, 9600bps, chiu di d liu c th l 5, 6, 7 hoc 8 bit v kt
hp vi cc bit Start, Stop, Parity to thnh mt khung (frame). Ngoi ra cng ny cn
c cc iu khin thu (Receive), pht (Trans), kim tra. Cch giao tip ny cho php
khong cch truyn d liu xa, tuy nhin tc truyn rt chm tc ti a l 20kbps.

103/369
Cu trc cng COM
Cng ni tip c s dng truyn d liu hai chiu gia my tnh v ngoi vi, c
cc u im sau:

- Khong cch truyn xa hn truyn song song.

- S dy kt ni t.

- C th truyn khng dy dng hng ngoi.

- C th ghp ni vi vi iu khin hay PLC (Programmable Logic Device).

- Cho php ni mng.

- C th tho lp thit b trong lc my tnh ang lm vic.

- C th cung cp ngun cho cc mch in n gin

Cc thit b ghp ni chia thnh 2 loi: DTE (Data Terminal Equipment) v DCE (Data
Communication Equipment). DCE l cc thit b trung gian nh MODEM cn DTE l
cc thit b tip nhn hay truyn d liu nh my tnh, PLC, vi iu khin, Vic trao
i

tn hiu thng thng qua 2 chn RxD (nhn) v TxD (truyn). Cc tn hiu cn li c
chc

nng h tr thit lp v iu khin qu trnh truyn, c gi l cc tn hiu bt tay


(handshake). u im ca qu trnh truyn dng tn hiu bt tay l c th kim sot
ng truyn.

Tn hiu truyn theo chun RS-232 ca EIA (Electronics Industry Associations). Chun
RS-232 quy nh mc logic 1 ng vi in p t -3V n -25V (mark), mc logic 0 ng
vi in p t 3V n 25V (space) v c kh nng cung cp dng t 10 mA n 20 mA.
Ngoi ra, tt c cc ng ra u c c tnh chng chp mch.

Chun RS-232 cho php truyn tn hiu vi tc n 20.000 bps nhng nu cp truyn
ngn c th ln n 115.200 bps.

Cc phng thc ni gia DTE v DCE:

- n cng (simplex connection): d liu ch c truyn theo 1 hng.

104/369
- Bn song cng ( half-duplex): d liu truyn theo 2 hng, nhng mi thi im ch
c truyn theo 1 hng.

- Song cng (full-duplex): s liu c truyn ng thi theo 2 hng.

nh dng ca khung truyn d liu theo chun RS-232 nh sau:

Khi khng truyn d liu, ng truyn s trng thi mark (in p -10V). Khi bt u
truyn, DTE s a ra xung Start (space: 10V) v sau ln lt truyn t D0 n D7
v Parity, cui cng l xung Stop (mark: -10V) khi phc trng thi ng truyn.
Dng tn hiu truyn m t nh sau (truyn k t A):

Hnh4.1Tnhiutruyncakt A Cc c tnh k thut ca chun RS-232 nh sau:

Chiu di cable cc i 15m


Tc d liu cc i 20 Kbps
in p ng ra cc i 25V
in p ng ra c ti 5V n 15V
Tr khng ti 3K n 7K
in p ng vo 15V
nhy ng vo 3V
Tr khng ng vo 3K n 7K

Cc tc truyn d liu thng dng trong cng ni tip l: 1200 bps, 4800 bps,

9600 bps v 19200 bps.

? Schn:

105/369
H n h 4 .2 S c h n c ng n i t i p

B tr chn ca cng COM

Cng COM c hai dng: u ni DB25 (25 chn) v u ni DB9 (9 chn) m t nh

hnh 4.2. ngha ca cc chn m t nh sau:

Tnh H ng
D25 D9 M t
iu tru y n
1 - - - Protected ground: ni t bo v
2 3 TxD DTEDCE Transmitted data: d liu truyn
3 2 RxD DCEDTE Received data: d liu nhn
4 7 RTS DTEDCE Request to send: DTE yu cu truyn d liu
5 8 CTS DCEDTE Clear to send: DCE sn sng nhn d liu
6 6 DSR DCEDTE Data set ready: DCE sn sng lm vic
7 5 GND - Ground: ni t (0V)
8 1 DCD DCEDTE Data carier detect: DCE pht hin sng mang
20 4 DTR DTEDCE Data terminal ready: DTE sn sng lm vic

106/369
22 9 RI DCEDTE Ring indicator: bo chung
23 - DSRD DCEDTE Data signal rate detector: d tc truyn
Transmit Signal Element Timing: tn hiu nh
24 - TSET DTEDCE
thitruyn i t DTE
Transmitter Signal Element Timing: tn hiu nh
15 - TSET DCEDTE
thitruyn t DCE truyn d liu
Receiver Signal Element Timing: tn hiu nh
17 - RSET DCEDTE
thitruyn t DCE truyn d liu
18 - LL Local Loopback: kim tra cng
Remote Loopback: To ra bi DCE khi tn hiu
21 - RL DCEDTE
nhnt DCE li
14 - STxD DTEDCE Secondary Transmitted Data
16 - SRxD DCEDTE Secondary Received Data
19 - SRTS DTEDCE Secondary Request To Send
13 - SCTS DCEDTE Secondary Clear To Send
12 - SDSRD DCEDTE Secondary Received Line Signal Detector
25 - TM Test Mode
9 - Dnh ring cho ch test
10 - Dnh ring cho ch test
11 Khng dng

107/369
Bi 11: THC HNH VI CC CHNG
TRNH GIAO TIP QUA CNG COM
Thc hnh vi cc chng trnh giao tip qua cng COM
Bi 1.

S dng VB6 thit lp, truyn d liu ra cng COM v nhn d liu v

Bi 2.

M phng chy ng c khi s dng VB6 iu khin.

108/369
Bi 12: VN NG B
Vn ng b ha nguyn mu (An Archetypal
Synchronization Problem )
Gi thit v sau iu bn tng dn bin ny khi bn nhn c mt yu cu v s
gim bt n khi bn sau hon thnh yu cu:

NTSTATUS DispatchPnp(PDEVICE_OBJECT fdo, PIRP Irp)

++lActiveRequests;

... // process PNP request

--lActiveRequests;

Ti chc chn l bn on nhn mt my m nh n phi khng phi l mt bin


tnh: n cn phi l mt b phn ca thit b m rng ca cc bn v th mi i tng
thit b c my m duy nht ca n. R sang vi ti, v gi v rng trnh iu khin
ca cc bn lun lun ch qun l mt thit b n. lm v d y ngha hn, gi
thit cui cng mt chc nng trong trnh iu khin ca cc bn s c gi l khi
no thi gian ca n xa i tng thit b ca cc bn. Bn c l mun tr hon
thao tc cho n khi khng c nhiu yu cu l ni bt hn, v th bn c l chn mt
s th ca my m:

NTSTATUS HandleRemoveDevice(PDEVICE_OBJECT fdo, PIRP Irp)

if (lActiveRequests)

<wait for all requests to complete>

IoDeleteDevice(fdo);

109/369
V d ny m t mt vn thc s, nhn tin, chng ti s dng tho lun vn
ny chng 6 trong nhng yu cu ca chng ta ca nhng yu cu Plug and Play
(PnP). Qun l vo/ra c th c gng loi b mt trong s nhng thit b ca chng
ta ti mt thi im khi nhng yu cu c kch hot, v chng ti cn phng iu
bng vic gi loi no ca my m. Ti s trnh by vi bn chng 6 s dng
IoAcquireRemoveLock nh th v mt s chc nng lin quan gii quyt vn .

Mt ch n np vn ng b ha kinh khng trong nhng on m ti ch cho bn


thy, nhng n tr nn hin nhin ch khi bn nhn ng sau s tng dn v gim nhng
thao tc bn trong DispatchPnp. Trn mt b x l x86, ngi bin son c l thc
hin h s dng nhng ch dn ny:

; ++lActiveRequests;

mov eax, lActiveRequests

add eax, 1

mov lActiveRequests, eax

; --lActiveRequests;

mov eax, lActiveRequests

sub eax, 1

mov lActiveRequests, eax

lm r vn ng b ha, gi s cho rng u tin c mt trc trc g trong


mt CPU n. Hnh dung hai lung l c hai ang c gng th tin ti xuyn qua
DispatchPnp ti cng mt thi gian. Chng ti bit h khng phi l c hai thc hin
ng ng thi bi v chng ti ch c mt CPU n cho h ti chia s. Nhng hnh
dung mt trong nhng lung thc hin gn kt thc chc nng v qun l ti ni
dung hin thi ca lActiveRequests vo trong thanh ghi EAX ch trc khi lung khc
chn trc n. Gi thit lActiveRequests cn bng vi 2 ti lc . Nh s chuyn i
b phn ca lung, h iu hnh la gi thanh ghi EAX (cha ng gi tr 2) nh phn
ca lung ang ri khi nh vn cnh u trong b nh.

Ch

110/369
By gi hnh dung rng lung khc qun l a m tng ln qua ti s bt u ca
DispatchPnp. N s tng dn lActiveRequests t 2 n 3 (bi v lung u tin cha
bao gi c ti cp nht bin). Nu lung u tin chn trc lung khc ny, h iu
hnh s khi phc u tin ng cnh ca lung, m bao gm gi tr 2 trong thanh ghi
EAX. Lung u tin by gi thu c tr 1 t EAX v ct gi kt qu sau
lActiveRequests. Ti im ny, lActiveRequests cha ng gi tr 1, m sai. u
xung l con ng, chng ti c l hp tp xa i tng thit b ca chng ta v
chng ti c rnh ghi b mt thc s ca ca mt yu cu vo/ra.

Vic gii quyt vn c bit ny th d dng trn mt my tnh x86 chng ti ch


thay th nhp/ thm / ct gi v nhp/ tr/ ct gi nhng dy lnh vi nhng ch dn
nguyn t:

; ++lActiveRequests;

inc lActiveRequests

111/369
; --lActiveRequests;

dec lActiveRequests

Trn mt Intel x86, nhng ch dn INC v DEC khng th c ngt, nh vy s


cha bao gi l mt trng hp trong mt lung c th c chn trc trong im
gia ca vic cp nht my m. Trong khi n ng, mc d, m ny cn l khng chc
chn trong mt mi trng b a x l bi v INC v DEC c thc hin trong vi
bc vi m. Kh d ca n cho 2 CPU khc nhau ang thc hin vi m ca h ch yu
t ra khi bc sao cho mt trong s h kt thc ln trn cp nht mt gi tr c. Vn
Multi-CPU c th cng c trnh trong kin trc x86 bng cch s dng mt tin t
LOCK:

; ++lActiveRequests;

lock inc lActiveRequests

; --lActiveRequests;

lock dec lActiveRequests

Ch dn LOCK thm vo u nhng s kha ngoi tt c CPU khc trong khi vi m cho
ch dn hin thi thc hin, do bo m s ton vn d liu.

Mt cch ng tic, khng phi tt c vn ng b ha c mt gii php d dng nh


vy. im ca v d ny l khng c cch gii quyt nh th no gii quyt mt vn
n gin trn mt trong nhng nn tng ni Windows XP chy nhng phn no
minh ha hai ngun ca kh khn: quyn u tin mua ca mt lung bi k khc trong
im gia ca mt s thay i trng thi v s thc hin ng thi ca nhng thao tc
state-change tng phn. Chng ti c th trnh kh khn bng vic thn trng s dng
nhng nguyn thy ng b ha, nhng i tng loi tr nh ln nhau nh vy,
ngn chn nhng lung khc trong khi d liu dng chung nhng truy nhp lung ca
chng ta. i khi khi s kha lung l khng cho php, chng ti c th trnh quyn
u tin bng cch s dng s quyn u tin IRQL, v chng ti c th ngn nga s
thc hin ng thi bng vic thn trng s dng nhng s kha xuay vng.

112/369
Mc yu cu Ngt (Interrupt Request Level )
Windows XP gn mt mc yu cu ngt ti mi ngt phn cng v ti mt s chn
la vi s kin phn mm. Mi CPU c IRQL ca mnh. Chng ti gn nhn nhng
mc IRQL khc nhau vi nhng tn nh PASSIVE_LEVEL, APC_LEVEL,. Hnh
4-1 minh ha phm vi ca nhng gi tr IRQL cho nn tng x86. (Ni chung, nhng gi
tr s ca IRQL ph thuc vo nn tng no bn ni v n). Hu ht thi gian, my tnh
thc hin trong kiu ngi s dng PASSIVE_LEVEL. Tt c kin thc ca cc bn
v cng vic nhng h iu hnh a nhim p dng PASSIVE_LEVEL nh th no.
iu , b lp lch biu c th chn trc mt lung ch cui ca mt phn chia thi
gian hay bi v mt lung quyn u tin bc cao tr nn xng ng chy. Nhng
lung cng c th l khi t trong khi h i nhng s kin xut hin.

Mt hot ng trn mt CPU cho ch c th c ngt bi mt hot ng m thc


hin mt IRQL bc cao.

Bn phi c quy tc ny nh cch my tnh lm. S ht hn ca mt thi gian ngn


dn dn ko theo b lp lch biu lung DISPATCH_LEVEL. B lp lch biu c th
lm mt lung khc nhau hin thi. Khi IRQL tr li PASSIVE_LEVEL, mt lung
khc nhau c chy. Tr phi n vn cn ng m u tin PASSIVE_LEVEL hot
ng l khng ngt qung bi hot ng PASSIVE_LEVEL th hai. Ti ngh rng s
gii thch ny l s bt b t m khng th tin c cho n khi n c ch ra ti ti m
s sp t ny cho php mt lung chy ti APC_LEVEL s c chn trc bi mt
lung khc nhau chy PASSIVE_LEVEL. C l mt s pht biu hu ch hn ca quy
tc ny l:

Mt hot ng trn mt CPU cho c th c ch ngt bi mt hot ng iu


thc hin mt IRQL bc cao. Ti mt hott ng hoc trn DISPATCH_LEVEL
khng th treo l lng thc hin hot ng khc ti hoc di IRQL then-current.

T mi CPU c IRQL ca mnh, n l kh d cho bt k CPU no trong mt my tnh


b a x l chy mt IRQL iu l t hn hoc chun y ti IRQL ca mi CPU
khc. Trong mc chnh tip theo, Ti s ni vi bn v nhng s kha xoay vng, m
kt hp bn trong - mt - CPU ng b ha hnh vi ca mt IRQL vi mt c ch ng
ca b a x l. Tuy nhin cho thi gian bt u, ti l cu chuyn gn nh g tnh c
gp mt CPU n.

CH :

Th tc lin lc v khng may DISPATCH_LEVEL c nhng tn tng t. Nhng th


tc lin lc c gi l bi v qun l vo/ra gi i nhng yu cu vo/ra ti chng.
DISPATCH_LEVEL v th c gi l v n l IRQL ti kernel thu pht lung trc y

113/369
chy khi quyt nh chy lung no k tip. (Thu pht lung chy SYNCH_LEVEL,
nu bn quan tm. y l cng nh DISPATCH_LEVEL trn mt my b x l n,
nu bn tht s quan tm.)

Gia DISPATCH_LEVEL v PROFILE_LEVEL l phng cho nhng mc ngt phn


cng khc nhau. Ni chung, mi thit b m pht sinh nhng ngt c mt IRQL m nh
ngha th t u tin ngt vis- as vis ca n i din nhng thit b khc. Mt driver
WDM khm ph IRQL ch) ngt ca n khi n nhn c mt yu cu IRP_MJ_PNP
vi m IRP_MN_START_DEVICE chc nng ph. Mc ngt ca thit b l mt trong
s nhiu tit mc ca thng tin cu hnh c i qua nh mt tham s ti yu cu ny.
Chng ti thng tham chiu ti mc ny nh thit b IRQL, hay DIRQL cho ngn.
DIRQL khng l mt mc yu cu n. Kh hn, n l IRQL cho ngt c lin h vi
thit b no di tho lun lc .

Tng kt, nhng driver c quan tm vi ba yu cu ngt nhng mc bnh thng:

PASSIVE_LEVEL, ti nhiu s lin lc no m nhng th tc v mt vi th


tc c bit thc hin
DISPATCH_LEVEL, ti StartIo v DPC no m nhng th tc thc hin
DIRQL, ti mt ngt dch v th tc thc hin

IRQL trong Thao tc

minh ha s quan trng ca IRQL, tham chiu ti Hnh 4-2, m minh ha mt trnh
t thi gian hp l ca nhng s kin trn mt CPU n. Ti s bt u ca chui,
CPU thc hin PASSIVE_LEVEL. thi gian t1, mt ngt n th tc dch v thc
hin IRQL-1, mt trong nhng mc gia DISPATCH_LEVEL v PROFILE_LEVEL.
Ri, thi gian t2, ngt khc n th tc dch v thc hin IRQL-2, m l t hn
IRQL-1. V quy tc c bn lun, CPU tip tc dch v ngt u tin. Khi u tin
ngt th tc dch v hon thnh thi gian t3, n c l i hi mt DPC. Nhng th
tc DPC thc hin DISPATCH_LEVEL. Vy th, quyn u tin cao nht ang xem
xt hot ng l th tc dch v cho ngt th 2, m bi vy thc hin tip theo. Khi n
kt thc t4, gi nh khng c g khc xut hin trong khi ch i, DPC s chy
DISPATCH_LEVEL. Khi nhng kt thc thng l DPC t5, IRQL c th b li
PASSIVE_LEVEL.

114/369
Hnh 4-2. u tin ngt trong hnh ng .

IRQL so snh vi nhng quyn u tin lung

Quyn u tin lung l mt khi nim rt khc nhau t IRQL. Quyn u tin Lung
kim sot nhng hot ng ca b lp lch biu trong vic quyt nh khi chn trc
chy nhng lung v ci g xu thnh chui bt u chy bc tip theo. " Quyn u
tin " duy nht m c ngha rng bt c ci g IRQLs trn APC_LEVEL l chnh
IRQL, v n kim sot nhng chng trnh no c th thc hin hn l vn cnh lung
m bn trong ci chng thc hin.

IRQL v s Phn trang

Mt h qu ca vic chy ti IRQL cao l h thng c tr nn khng c kh nng


ca vic dch v nhng li trang. Quy tc ny hm vic l n gin c pht biu:

M thc hin ti hoc trn DISPATCH_LEVEL khng phi l trang nguyn nhn cc
li.

Mt s lin quan ca quy tc ny l bt k th tc con trong trnh iu khin ca cc


bn m iu thc hin ti hoc hoc trn cc DISPATCH_LEVEL phi c b nh
trong nonpaged. Hn na, tt c d liu bn truy nhp trong mt th tc con nh vy
cng phi c b nh trong nonpaged. Cui cng, trong khi IRQL tng ln, nhng th
tc h tr kernel-mode t hn v t hn sn sng cho s s dng ca cc bn.

115/369
Ti liu DDK r rng pht biu nhng s hn ch IRQL trn nhng th tc h tr. Chng
hn, mc vo cho KeWaitForSingleObject ch bo hai s hn ch:

i trng gi phi c chy ti hoc di DISPATCH_LEVEL.


Nu gi nonzero mt thi gian ch l khong thi gian xc nh trong cuc gi,
i tng gi phi c chy chnh xc di DISPATCH_LEVEL.

Kim sot hon ton IRQL(Implicitly Controlling IRQL)

Hu ht thi gian, h thng gi nhng th tc trong trnh iu khin ca cc bn ti


IRQL ng cho nhng hot ng bn gi nh thc hin. Mc d ti khng bn lun
chi tit nhiu nhng th tc ny, ti mun a cho bn mt v d ca iu m ti thy
c ngha. Bt gp u tin ca cc bn vi mt yu cu vo/ra mi xut hin khi qun
l vo/ra gi l mt trong s nhng th tc lin lc ca cc bn x l mt IRP. S
gi thng thng xut hin ti PASSIVE_LEVEL bi v bn c l cn n vic ngn
chn lung gi hng ti v bn c l cn gi l bt k th tc h tr no. Bn c
th khng ngn chn mt lung mt IRQL bc cao, tt nhin, v PASSIVE_LEVEL
l mc m c nhng s hn ch t nht trn nhng th tc h tr bn c th gi.

Mc d n l kh d cho bn r rng kim sot IRQL (v ti s gii thch nh th no


trong mc tip theo), him khi c bt c l do g lm nh th, v trong th gia cc
nhu cu ca bn v mc m cc h thng cc cuc gi bn. Vy th, bn khng cn phi
nhn c treo ln trn IRQL m bn ang thi hnh ti thi im t khong thi gian rt
ngn : iu gn nh chc chn mc chnh xc cho cng vic bn ang v phi
lm ngay sau .

Kim sot r rng IRQL (Explicitly Controlling IRQL )

Khi cn thit, bn c th tng v sau ny h thp xung IRQL trn b x l hin thi
bng vic gi l KeRaiseIrql v KeLowerIrql. Chng hn, t vic bn trong mt th tc
chy PASSIVE_LEVEL:

KIRQL oldirql;

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

KeRaiseIrql(DISPATCH_LEVEL, &oldirql);

116/369
KeLowerIrql(oldirql);

1. KIRQL l tn typedef cho mt s nguyn m gi mt gi tr IRQL. Chng ti


s cn mt bin gi IRQL hin thi, v th chng ti khai bo n cch ny.
2. iu ny th hin khng nh mt iu kin cn thit gi KeRaiseIrql: IRQL
mi phi ln hn hoc bng mc hin ti. Nu quan h l khng ng,
KeRaiseIrql s bugcheck (iu , bo co mt li thng qua mt mn hnh
mu xanh ca s cht).
3. KeRaiseIrql nng IRQL hin thi ti mc c ch r bi i s u tin. N
cng ct gi IRQL hin thi ti v tr c tr vo bi i s th hai. Trong v
d ny, chng ti l nng IRQL ti DISPATCH_LEVEL v ct gi mc hin
thi oldirql.
4. Sau khi thc hin d m no chng ti c mun thc hin ti IRQL cao,
chng ti h thp xung mc yu cu quay tr li gi tr trc y ca n bng
vic gi l KeLowerIrql v ch r gi tr oldirql trc c tr li bi
KeRaiseIrql.

Sau khi nng IRQL, bn cn phi dn dn khi phc n ti gi tr ban u. Cch khc,
nhng s gi thit khc nhau lm bi m bn gi sau hoc bng cch gi l m m
bn c th bt ra sau ny c khng chnh xc. Ti liu DDK ni rng bn phi
lun lun gi cho KeLowerIrqlwith cng gi tr nh m tr li bi vic gi ngay lp
tc KeRaiseIrql, tr phi thng tin ny khng tht s chnh xc. Quy tc duy nht m
KeLowerIrql tht s p dng l IRQL mi phi l t hn hoc bng vi mt IRQL hin
hnh. Bn c th h thp xung IRQL trong nhng bc nu bn mun.

117/369
Kha xoay vng (Spin Locks )
gip bn ng b ha truy nhp ti d liu dng chung trong th gii a x l cn
i ca Windows XP, kernel cho bn nh ngha bt k s ca cc i tng kha
xoay vng no. thu nhn mt kha xoay vng, m trn mt CPU thc hin mt trong
nhng thao tc nguyn t m nhng s th v sau c t mt bin k c theo mt
cch m khng c CPU khc c th truy nhp bin cho n thao tc hon thnh. Nu s
th ch ra s kha trc t do, chng trnh tip tc. Nu s th ch ra s kha
th trc c gi, chng trnh lp li test-and-set trong mt vng lp cht: n
l spins. Dn dn ch nhn gii phng s kha bng vic t li bin, v ci l mt
trong s s ch i qu trnh hot ng test-and-set ca CPU s bo co s kha nh t
do.

Hnh 4-3 minh ha khi nim ca vic s dng mt s kha xoay vng. Gi thit chng
ti c " ti nguyn " no m c l c s dng ng thi trn hai CPU khc nhau.
lm v d c th, hnh dung rng ti nguyn l t bo LIST_ENTRY m neo mt bn
k lin kt ca IRPs. Danh sch c l c truy nhp bi mt hoc nhiu th tc gi
i, mt s hy b thng l, mt DPC thng l,.... Bt k s no ca nhng th tc
ny c l l ang thc hin ng thi trn cc CPU khc nhau v th sa i danh
sch kt hp. ngn nga s hn lon, chng ti lin tng mt kha xoay vng vi
iu ny " ti nguyn."

Hnh 4-3. S dng mt kha xoay vng bo v mt ti nguyn dng chung.

Gi thit by gi m m thc hin trn CPU-A mun truy nhp ti nguyn dng chung
thi gian t1. N thu nhn s kha xoay vng v bt u s truy nhp ca n. Khng
lu na v sau, thi gian t2, m thc hin trn CPU-B cng mun truy nhp cng ti
nguyn. CPU- B chng trnh th thu nhn s kha xoay vng. T CPU mt hin thi
s hu s kha xoay vng, CPU B nhng s xoay vng trong mt vng lp cht, lin
tc kim tra v kim tra li kha xoay vng nhn thy liu c phi n tr nn t do.

118/369
Khi no CPU-A phin bn kha ti thi gian t3, CPU-B tm thy kha t do v nhng
quyn i n. CPU-B gii phng s truy nhp ti ti nguyn. Cui cng, thi gian
t4, CPU-B kt thc s truy nhp ca n v gii phng kha CPU-B.

Vic thu nhn mt kha xoay vng nng IRQL ti DISPATCH_LEVEL t ng. Vy
th, m m thu nhn mt kha phi c nh s trang b nh v khng phi ngn chn
lung m trong n chy. (C mt ngoi l trong Windows XP v nhng h thng sau.
KeAcquireInterruptSpinLock nng IRQL ti DIRQL cho mt ngt v i hi kha xoay
vng lin quan n ngt.)

Nh mt h qu hin nhin thc t trc y, bn c th i hi mt kha xoay vng ch


khi bn ang chy ti hoc di DISPATCH_LEVEL. Ni ti, kernel th c th thu
nhn nhng s kha quay trn mt IRQL cao hn DISPATCH_LEVEL, nhng bn
v ti khng c kh nng hon thnh chin cng .

Thc t khc v nhng kha xoay vng l rt t cng c ch xut hin trn mt CPU iu
i mt kha xoay vng. S xoay vng xy ra DISPATCH_LEVEL vi nhng
ngt c cho php, v vy mt CPU l vic i mt kha xoay vng c th dch
v nhng ngt phn cng. Nhng trnh lm hi s thc hin, bn cn ti gin s
lng ca cng vic bn trong khi gi mt quay trn kha CPU khc no thch hp
mun.

Nhn tin, hai CPUs c th ng thi gi hai kha quay trn khc nhau. S sp t ny
c ngha: bn lin tng mt s kha quay trn vi mt ti nguyn dng chung nht
nh, hay tp hp no ca nhng ti nguyn dng chung. l khng c lp lun
a ln x l lin quan n nhng ti nguyn khc nhau bo v bi nhng kha quay
trn khc nhau.

Lm vic vi nhng s kha Quay trn

s dng mt s kha quay trn r rng, nh phn lu tr cho mt i tng


KSPIN_LOCK trong nh s trang k c. Ri gi l KeInitializeSpinLock khi to
i tng. Mun hn, trong lc vic chy ti hoc di DISPATCH_LEVEL, thu
nhn kha, thc hin cng vic m cn c bo v t s giao thoa, v sau gii phng
kha. Chng hn, gi thit m rng thit b ca cc bn cha ng mt QLock c tn
kha quay trn m bn s dng bo v s truy nhp ti mt hng i IRP c bit
bn c thit lp. Bn s khi to s kha ny trong chc nng AddDevice ca cc bn:

typedef struct _DEVICE_EXTENSION {

KSPIN_LOCK QLock;

119/369
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS AddDevice(...)

PDEVICE_EXTENSION pdx = ...;

KeInitializeSpinLock(&pdx->QLock);

Ni khc trong trnh iu khin ca cc bn, li ni trong chc nng lin lc cho kiu
IRP no , bn c th i hi ( v nhanh l phin bn) s kha xung quanh s thao tc
hng i no m bn cn thc hin. Ch rng chc nng phi trong nh s trang
k c v n thc hin trong mt thi gian ti mt IRQL cao.

NTSTATUS DispatchSomething(...)

KIRQL oldirql;

PDEVICE_EXTENSION pdx = ...;

KeAcquireSpinLock(&pdx->QLock, &oldirql);

KeReleaseSpinLock(&pdx->QLock, oldirql);

120/369
1. Khi KeAcquireSpinLock thu nhn s kha quay trn, n cng nng IRQL ti
DISPATCH_LEVEL v quay tr li mc hin hnh trong bin ti nhng im
i s th hai.
2. Khi KeReleaseSpinLock gii phng s kha quay trn, n cng h thp xung
IRQL quay tr li gi tr c ch r trong i s th hai.

Nu bn bit bn thc hin DISPATCH_LEVEL, bn c th ct gi mt t thi gian


bng vic gi l hai th tc c bit. K thut ny l thch hp, chng hn, trong DPC,
StartIo, v nhng th tc trnh iu khin khc thc hin DISPATCH_LEVEL:

KeAcquireSpinLockAtDpcLevel(&pdx->QLock);

KeReleaseSpinLockFromDpcLevel(&pdx->QLock);

121/369
Cc i tng Kernel Dispatcher (Kernel Dispatcher
Objects )
Kernel cung cp nm kiu ca nhng i tng ng b ha m bn c th s dng
kim sot lung ca nhng lung khng chuyn quyn. Nhn thy Bng 4-1 cho mt
tm lc ca nhng kiu i tng thu pht nhn ny v nhng s s dng ca h. Vo
mt vi khonh khc, mt trong s i tng ny trong mt ca hai trng thi: c
bo hiu hay khng phi - bo hiu. Ti nhng ln khi n tha nhn c cho bn
ngn chn mt lung trong vn cnh ca bn ang chy, bn c th i mt hoc nhiu
i tng t n bo hiu trng thi bng vic gi l KeWaitForSingleObject hay
KeWaitForMultipleObjects. Kernel cng cung cp nhng th tc cho kKhi to v kim
sot tnh trng ca mt trong cc i trng ny.

Bng 4-1. Nhng


i tng thu
pht Kernel
i tng Kiu d liu M t
Ngn chn mt lung cho n khi lung khc
Event KEVENT
no pht hin mt s kin xut hin
c s dng thay v mt s kin khi nhng
Semaphore KSEMAPHORE mt s gi s lng s ch i chuyn quyn
c th c tha mn
Loi tr nhng lung khc t vic thc hin
Mutex KMUTEX
mt mc c bit ca m
Thc hin nhng tr hon ca mt lung trong
Timer KTIMER
mt thi gian cho
Ngn chn mt lung cho n khi lung khc
Thread KTHREAD
hon thnh

Trong vi mc tip theo, Ti s m t lm sao s dng nhng i tng thu pht


kernel. Ti s bt u bng vic gii thch khi bn c th ngn chn mt lung bng vic
gi mt ca nhng nguyn thy ch i, v sau Ti s bn lun nhng th tc h tr
m bn s dng vi ton b cc kiu i tng. Ti s kt thc mc ny bng vic bn
lun nhng khi nim lin quan ca nhng s bo ng lung v s giao hng gi th
tc khng ng b.

122/369
hiu khi no v nh th no n tha nhn c mt trnh iu khin WDM ngn
chn mt lung trn mt i tng thu pht kernel. Ni chung, d lung no ang thc
hin lc ca mt phn mm hay ngt phn cng tip tc l lung hin thi trong khi
nhng x l kernel ngt. Chng ti ni ca vic thc hin m kernel-mode trong vn
cnh ca lung hin thi ny. Trong s p li ti nhng ngt ca nhng cch thc khc
nhau, b lp lch biu c l quyt nh chuyn nhng lung, tt nhin, ti trng hp
no mt lung mi tr nn " hin hnh."

Thng thng, ch mt trnh iu khin mc- cao nht c th bit cho chc chn iu
n l s vn dng trong mt vn cnh lung khng chuyn quyn. Gi s cho php bn
l mt s lin lc thng l trong mt trnh iu khin mc- thp hn, v bn ngc nhin
c hay khng bn c gi l trong mt lung chuyn quyn. Nu trnh iu khin
mc- cao nht trc tip ch gi bn mt IRP t s lin lc thng l ca n, bn lm
trong bn gc, khng chuyn quyn, lung. Nhng gi thit rng trnh iu khin c
c mang mt IRP vo mt hng i v sau tr li ti ng dng. Trnh iu khin
loi b IRP t hng i trong mt lung chuyn quyn v sau c gi n hay
IRP khc n bn. Tr phi bn bit iu l khng xy ra, bn cn phi gi thit bn
trong mt lung chuyn quyn nu bn khng phi l trnh iu khin mc- cao nht.

Mc d iu m Ti ni, trong nhiu hon cnh bn c th chc chn ca vn cnh


lung. Cc th tc DriverEntry v AddDevice ca cc bn c gi l trong mt lung
h thng m bn c th ngn chn nu bn cn ti. Bn chin khng thng thng cn
ti khi r rng bn trong nhng th tc ny, tr phi bn c th nu bn mun ti.
Bn cng nhn c nhng yu cu IRP_MJ_PNP trong mt lung h thng. Trong
nhiu trng hp, bn phi ngn chn lung x l chnh xc yu cu. Cui cng,
bn s i khi nhn nhng yu cu vo/ra trc tip t mt ng dng, trong trng hp
no bn s bit bn trong mt lung thuc v ng dng.

i trn mt i tng Thu pht n

Bn gi l KeWaitForSingleObject nh c minh ha trong v d sau y:

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

LARGE_INTEGER timeout;

NTSTATUS status = KeWaitForSingleObject(object, WaitReason,

WaitMode, Alertable, &timeout);

Nh c gi bi ASSERT, bn phi l ang thc hin ti hoc di


DISPATCH_LEVEL thm ch gi l th tc dch v ny.

123/369
Trong s gi ny, i tng tr vo i tng bn mun i trn. Mc d i s ny
c nh my nh mt PVOID, n cn phi l mt con tr ti mt trong nhng i
tng thu pht c lit k trong Bng 4-1. i tng phi trong c nh s trang
k c-chng hn, trong mt cu trc m rng thit b hay vng d liu khc c cp
pht t nh s trang pool. Cho a s nhng mc ch, ngn xp thc hin c th c
xem xt c nh s trang.

i trn nhiu i tng Thu pht(Waiting on Multiple Dispatcher Objects )

KeWaitForMultipleObjects l mt s tay chc nng ti KeWaitForSingleObjectthat


bn s dng khi bn mun i cho mt hay tt c vi i tng thu pht ng thi.
Gi l chc nng ny nh trong v d ny:

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

LARGE_INTEGER timeout;

NTSTATUS status = KeWaitForMultipleObjects(count, objects,

WaitType, WaitReason, WaitMode, Alertable, &timeout, waitblocks);

y nhng i tng l a ch ca mt mng ca nhng con tr ti nhng i tng


thu pht, v s m l s ca nhng con tr trong mng. S m phi l t hn nh chun
y ti gi tr MAXIMUM_WAIT_OBJECTS, m hin thi cn bng vi 64. Mng, cng
nh ton b nhng i tng ti nhng phn t no (ca) mng ch, phi l trong nh
s trang k c. WaitType l mt trong nhng gi tr lit k WaitAll hay WaitAny v ch
r liu c phi bn mun i cho n tt c cc i tng ng thi bo hiu trng thi
hay liu c phi, thay vo , bn mun i cho n khi bt k nhng i tng no
c bo hiu.

i s waitblocks tr vo mt mng ca cc cu trc KWAIT_BLOCK m kernel s


s dng iu hnh thao tc ch i. Bn khng cn khi to nhng cu trc ny
trong bt k cch no- kernel ch cn bit kho u cho nhm ca nhng khi ch
i m n s thng ghi tnh trng ca ton b nhng i tng trong thi gian ch
i. Nu bn i mt s nh ca nhng i tng (c bit, mt s khng c ln hn
THREAD_WAIT_OBJECTS, m hin thi cn bng vi 3), bn c th cung cp NULL
cho tham s ny. Nu bn cung cp NULL, KeWaitForMultipleObjects s dng mt
mng preallocated ca khi ch i m tn ti trong i tng lung. Nu bn i nhiu
nhng i tng hn iu ny, bn phi cung cp nh s trang k c iu l t nht
count * sizeof(KWAIT_BLOCK) nhng byte trong di.

Nhng l l cn li ti KeWaitForMultipleObjects l ging nh tng ng nhng l l


ti KeWaitForSingleObject, v a s tr li nhng m c cng ngha.

124/369
Nu bn ch r WaitAll, gi tr STATUS_SUCCESS tr li c ch bo rng tt c cc
i tng qun l t n bo hiu trng thi ng thi. Nu bn ch r WaitAny,
gi tr tr li bng s th bng ch s mng nhng i tng ca i tng n m tha
mn s ch i. Nu hn mt trong nhng i tng tnh c c bo hiu, bn s
c ni v mt trong s chng c th lowest- numbered ca tt c th m c bo
hiu vo khonh khc , tr phi c th mt vi cch khc. Bn c th ngh v php
cng gi tr STATUS_WAIT_0 ny cng vi ch s mng. Bn khng c th n gin
thc hin s th NT_SUCCESS thng thng ca trng thi tr v trc khi vic rt
ch s mng t m tnh trng, tuy nhin, bi v cc m tr v kh d khc (bao gm
STATUS_TIMEOUT, STATUS_ALERTED, v STATUS_USER_APC) cng i qua
s th. M s dng thch iu ny:

NTSTATUS status = KeWaitForMultipleObjects(...);

if ((ULONG) status < count)

ULONG iSignaled = (ULONG) status - (ULONG) STATUS_WAIT_0;

Khi KeWaitForMultipleObjects tr li mt m trng thi bng mt i tng ch s


mng trong mt trng hp WaitAny, n cng thc hin nhng thao tc c yu cu
bi i tng . Nu nhiu i tng c bo hiu v bn ch r WaitAny, nhng
thao tc ch c thc hin cho mt i tng, iu cho rng tha mn s ch i
v ch s c tr v. i tng l khng nht thit u tin mt trong mng ca cc
bn m tnh c c bo hiu.

Nhng s kin Nhn Kernel

Bn s dng nhng chc nng dch v c lit k trong Bng 4-2 lm vic vi
nhng i tng s kin kernel. khi to mt i tng s kin, d tr u tin
nonpaged cho mt i tng ca kiu KEVENT v sau gi l KeInitializeEvent:

ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

KeInitializeEvent(event, EventType, initialstate);

S kin l a ch ca i tng s kin. EventType l mt trong nhng gi tr lit k


NotificationEvent v SynchronizationEvent. Mt s kin thng bo c c im , khi
l s thit lp ti trng thi bo hiu, n li bo hiu cho n khi n l r rng
lp li ti trng thi khng bo hiu. Hn na, tt c cc lung m i trn mt s kin
thng bo c gii phng khi s kin c bo hiu. Ci ny cng nh mt s kin

125/369
c t li bi ti liu trong kiu ngi s dng. Mt s kin ng b ha, mt khc,
c t li ti trng thi khng - bo hiu ngay khi mt lung n c gii phng.
y l ci g xy ra trong kiu ngi s dng khi ngi no gi l SetEvent trn mt
i tng s kin t khi ng li. Thao tc duy nht c thc hin trn mt i tng
s kin bi KeWaitXxx s t li mt s kin ng b ha ti khng phi - bo hiu.
Cui cng, initialstate TRUE ch r rng trng thi ban u ca s kin s c bo hiu
v FALSE ch r trng thi ban u khng phi - bo hiu.

Bng 4-2. Cc chc nng dch v cho s s


dng vi nhng i tng s kin Kernel
Chc nng dch v M t
S kin nhng thit lp khng-bo
KeClearEvent hiu; khng bo co trng thi lin
trc
KeInitializeEvent Khi to i tng s kin
Xc nh trng thi hin ti ca s kin
KeReadStateEvent
(Windows XP v ch Windows 2000)
S kin nhng thit lp khng-bo
KeResetEvent
hiu; trng thi lin trc tr li
S kin nhng thit lp c bo hiu;
KeSetEvent
trng thi lin trc tr li

CH :

Trong dy ny ca nhng mc trn nhng nguyn thy ng b ha, ti lp li


nhng s hn ch IRQL m ti liu DDK m t. Trong phin bn hin thi ca
Microsoft Windows XP, DDK i khi hn ch hn h iu hnh tht s. Chng hn,
KeClearEvent c th c gi l ti bt k IRQL no, khng phi ch ti hoc di
DISPATCH_LEVEL. KeInitializeEvent c th c gi bt k IRQL no, khng phi
ch PASSIVE_LEVEL. Tuy nhin, bn cn phi lu tm ti nhng s pht biu trong
DDK nh tng ng ti vic ni m Microsoft c l mt ngy no p t ly
s hn ch ti liu, no phi khng c nhng c gng bo co trng thi tht s ca
nhng vn .

Bn c th gi KeSetEvent t mt s kin trng thi bo hiu:

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

LONG wassignaled = KeSetEvent(event, boost, wait);

126/369
Nh bao hm bi ASSERT, bn phi ang l chy ti hoc di DISPATCH_LEVEL
gi chc nng ny. i s s kin l mt con tr ti i tng s kin trong cu hi,
v s tng l mt gi tr c thm vo mt lung i quyn u tin nu vic t s
kin dn ti tha mn ngi no i. Nhn thy bn cnh (" m i s th ba lm
phin ti KeSetEvent ") cho mt gii thch ca i s Boolean i i s, mt trnh iu
khin WDM no m hu nh cha bao gi ch nh TRUE. Gi tr tr li khc khng
nu s kin bo hiu trng thi trc khi gi v 0 nu s kin l khng khng - Bo
hiu trng thi.

Mt b lp lch biu a nhim cn thc y gi to quyn u tin ca mt lung m i


nhng thao tc vo/ra hay nhng i tng ng b ha trnh lm cht i nhng
lung m tiu ph nhiu thi gian i. y l bi v mt lung m nhng khi cho l
do no ni chung t b thi gian t i ca n v khng thng tr li CPU cho n
khi n c mt quyn u tin mt cch tng i cao hn so vi lung xng ng khc
hay lung khc m c cng quyn u tin kt thc nhng thi gian t i ca chng. Mt
lung nhng khi khng bao gi l iu , tuy nhin, hiu c hon thnh nhng
lt thi gian ca n. Tr phi mt s tng c p dng ti lung m cc khi lp i lp
li nhiu ln, bi vy, n s tiu ph nhiu thi gian i nhng lung CPU- bound kt
thc thi gian t i ca chng.

Bn v ti lun lun khng chin thng c mt tng tt ca gi tr no s


dng cho mt s tng quyn u tin. Mt kinh nghim tt i theo sau s ch r
IO_NO_INCREMENT tr phi bn c mt l do tt khng phi ti. Nu vic t s kin
s thc gic trn mt lung iu quan h vi mt chy trn d liu time-sensitive
(nh mt trnh iu khin m thanh), cung cp s tng iu thch hp ti h nh thit
b ( nh IO_SOUND_INCREMENT). Th quan trng s khng phi thc y ngi
trng i cho mt l do ngu ngc. Chng hn, nu bn th x l mt yu cu ng b
IRP_MJ_PNP xem Chng 6 bn s ang i nhng trnh iu khin lower-level
x l IRP trc khi bn theo ui, v s th tc hon thnh ca cc bn s gi l
KeSetEvent. T nhng yu cu Plug and Play khng c tuyn b c bit trn b x l
v ch xut hin him khi xy ra, ch r IO_NO_INCREMENT, thm ch cho mt card
m thanh.

S dng mt S kin ng b ha cho s loi tr ln nhau (Using a Synchronization


Event for Mutual Exclusion)

Ti s ni vi nhng bn sau trong chng ny v hai kiu i tng loi tr ln


nhau mt kernel mutex v mt mutex nhanh thc hin bn c th s dng ti gii
hn s truy nhp chia s d liu trong nhng hon cnh trong mt kha quay trn
khng thch hp cho l do no . i khi bn c th n gin s dng mt s kin
ng b ha cho mc ch ny. u tin nh ngha s kin nh s trang k c, nh
sau:

127/369
typedef struct _DEVICE_EXTENSION {

KEVENT lock;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

Initialize it as a synchronization event in the signaled state:

KeInitializeEvent(&pdx->lock, SynchronizationEvent, TRUE);

Vo tit din ti hn lightweight ca cc bn bng vic i trn s kin. li bi s


thit t s kin.

KeWaitForSingleObject(&pdx->lock, Executive, KernelMode,

FALSE, NULL);

KeSetEvent(&pdx->lock, EVENT_INCREMENT, FALSE);

Ch s dng mnh khe ny trong mt lung h thng, Tuy nhin, cn tr mt s gi


user-mode ti NtSuspendThread to ra mt s b tc. (S b tc ny c th d dng
xy ra nu mt trnh g ri user-mode ang chy trn cng qu trnh.) Nu bn chy
trong mt lung ngi s dng, bn cn phi thch s dng mt mutex nhanh thc hin.
Khng s dng mnh khe ny cht no cho m, iu thc hin trong ng dn
phn trang, nh cch c gii thch sau lin quan n " khng an ton " ca vic thu
nhn mt thc hin nhanh mutex.

Kernel nh tn hiu (Kernel Semaphores )

Mt n hiu kernel l mt my m s nguyn vi ng ngha hc ng b ha c kt


hp. Xem xt n bo hiu khi my m khng nh v khng phi - bo hiu khi my
m l 0. My m khng th m nhim mt gi tr tiu cc. Vic gii phng mt n
hiu tng my m, trong khi m mt cch thnh cng i trn mt s gim bt n hiu
my m. Nu s gim bt lm cho s m l 0, n hiu c xem xt khng phi-
bo hiu, vi h qu nhng i tng gi KeWaitXxx khc m ni n tm thy n bo
hiu khi bt buc. Ghi ch m nu nhiu lung hn ang i mt n hiu so vi gi
tr ca my m, khng phi tt c lung i s c gii ta.

128/369
kernel cung cp ba chc nng dch v kim sot trng thi ca mt i tng
n hiu. (Xem bng 4-3.) Bn khi to mt n hiu bng vic gi chc nng
PASSIVE_LEVEL sau y:

ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

KeInitializeSemaphore(semaphore, count, limit);

Trong s gi ny, n hiu tr vo mt i tng KSEMAPHORE nh s trang k c.


Bin m l gi tr ban u ca my m, v gii hn ca tr s cc i m my m s
c cho php m nhim, m phi ln nh s m ban u.

Bng 4-3. Nhng chc nng dch v cho s s


dng vi nhng i tng nh tn hiu Kernel
Service Function M t
KeInitializeSemaphore Khi to i tng n hiu
Xc nh trng thi hin thi ca
KeReadStateSemaphore
n hiu
Nhng s ng cng nh tn hiu
KeReleaseSemaphore
i tng ti trng thi bo hiu

Nu bn to ra mt n hiu vi mt gii hn ca 1, i tng c phn tng t nh


mt mutex trong iu duy nht mt lung ti mt thi im s c kh nng i hi
n. Mt kernel mutex c mt s c tnh m mt s thiu n hiu, tuy nhin, gip
ngn nga nhng s b tc. Tng ng, gn nh khng c im no trong vic
to ra mt n hiu vi mt gii hn ca 1.

Nu bn to ra mt n hiu vi mt gii hn ln hn 1, bn c mt i tng m cho


php nhiu lung truy nhp mt ti nguyn cho. Mt nh l quen thuc trong nhng
mnh lnh l thuyt hng i m cung cp mt hng i n cho nhiu ngi phc v
r rng hn ( iu , dn n t s bin i hn trong nhng thi gian i) so vi vic
cung cp mt ngn cch hng i cho ton b cc my ch ring. Thi gian i trung
bnh ging nh trong c hai trng hp, nhng s bin i trong nhng thi gian i l
nh hn vi hng i n. (y ti sao l nhng hng i trong nhng kho ngy cng
tng c t chc sao cho nhng khch hng i trong mt dng n cho th k sn
c tip theo.) Loi n hiu ny cho php bn t chc mt s ng cng ca phn mm
hay phn cng nhng my ch tn dng nh l .

Ch nhn (hay mt trong nhng ch nhn) ca mt n hiu gii phng tuyn b ca n


ti n hiu bng vic gi l KeReleaseSemaphore:

129/369
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

LONG wassignaled = KeReleaseSemaphore(semaphore, boost,

delta, wait);

Thao tc ny thm delta, m phi c tch cc, ti my m c lin quan n nh


tn hiu , do mang n hiu vo bo hiu trng thi v cho php nhng lung khc
s c gii phng. Trong a s nhng trng hp, bn s ch r 1 tham s ny ch
bo rng mt ngi khiu ni ca n hiu ang gii phng tuyn b ca n. S tng
v nhng tham s i c cng nhp khu vi nhng tham s tng ng ti KeSetEvent,
c bn lun trc . Gi tr tr li l 0 nu trng thi trc y ca n hiu khng
c bo hiu v khc khng nu trng thi trc y c bo hiu.

KeReleaseSemaphore khng cho php bn tng my m bn ngoi gii hn c ch


r khi bn khi to n hiu. Nu bn th, n khng iu chnh my m cht no, v
n nng mt ngoi l vi m STATUS_SEMAPHORE_LIMIT_EXCEEDED. Tr phi
ngi no c mt chng trnh x l c bit c cu trc by ngoi l, mt kim
tra li s dn n kt qu.

Bn c th cng thm vn trng thi hin thi ca mt n hiu vi iu gi ny:

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

LONG signaled = KeReadStateSemaphore(semaphore);

Gi tr tr li khc khng nu n hiu c bo hiu v 0 nu n hiu khng bo hiu.


Bn khng nn gi nh rng gi tr tr li l hin nay gi tr ca my m n c
th l bt k gi tr khc khng no nu my m xc thc.

C c ni bn tt c iu ny v s dng kernel nh th no nh tn hiu, Ti


cm thy Ti nn ni bn iu Ti cha bao gi nhn thy mt trnh iu khin m
s dng mt trong s chng.

Kernel Timers

Kernel cung cp mt i tng timer m mt s chc nng ging nh mt s kin m


t ng bo hiu ti mt thi gian tuyt i xc nh hay sau mt khong xc nh. N
cng kh d to ra mt thit b bm gi m bo hiu nhiu ln v thu xp cho mt
DPC phn hi i theo sau s ht hn ca thit b bm gi. Bng 4-5 lit k nhng chc
nng dch v bn s dng vi cc i tng thit b bm gi.

130/369
Bng 4-5. Cc chc nng dch v cho
vic s dng vi nhng i tng Thit
b bm gi Kernel
Service Function M t
KeCancelTimer Hy b mt thit b bm gi tch cc
Khi to mt thit b bm gi thng bo
KeInitializeTimer
trc kia
Khi to mt thng bo hay thng bo c
KeInitializeTimerEx c trng lp i lp li hay thit b bm
gi ng b ha
Xc nh trng thi hin thi ca mt thit
KeReadStateTimer
b bm gi
Ch r thi gian ht hn cho mt thng
KeSetTimer
bo thit b bm gi
Ch r s ht hn thi gian v nhng
KeSetTimerEx
thuc tnh khc ca mt thit b bm gi

C vi kch bn cch dng khc nhau cho nhng thit b bm gi, ti m t trong trong
vi mc tip theo:

Thit b bm gi c dng nh mt s kin t bo hiu


Thit b bm gi vi mt DPC thng l s c gi l khi mt thit b bm
gi ht hn
Thit b bm gi tun hon thng gi trn mt DPC thng l v trn mt ln
na

Nhng thit b bm gi thng bo c dng nh nhng s kin(Notification


Timers Used like Events):

Trong kch bn ny, chng ti s to ra mt i tng thit b bm gi thng bo v ch


i cho n khi n ht hn. u tin cp pht mt i tng KTIMER trong vic nh
s trang k c. Ri, chy ti hoc di DISPATCH_LEVEL, khi to i tng thit
b bm gi, nh c cho thy y:

PKTIMER timer; // <== someone gives you this

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

KeInitializeTimer(timer);

131/369
Ti im ny, thit b bm gi khng - bo hiu trng thi v khng m xung-mt s
ch i trn thit b bm gi cha bao gi c tha mn. bt u s m thit b
bm gi, gi l KeSetTimer nh sau:

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

LARGE_INTEGER duetime;

BOOLEAN wascounting = KeSetTimer(timer, duetime, NULL);

Gi tr duetime l mt gi tr thi gian truyn 64- bit c biu th n v


100-nanosecond. Nu gi tr l i lng dng, n l mt thi gian tuyt i tng i
ti cng thng ging 1, 1601, k nguyn c dng cho thit b bm gi h thng. Nu
gi tr l ph nh, n l mt khong tng i i vi thi gian hin ti. Nu bn ch
r mt thi gian tuyt i, mt s thay i k tip ti ng h h thng thay i khong
thi gian ca timeout bn kinh nghim. iu , thit b bm gi khng ht hn cho
n khi ng h h thng cn bng vi hoc vt hn d gi tr tuyt i no bn ch
nh. Trong s tng phn, nu bn ch r mt dng tng quan timeout, khong thi
gian ca timeout bn kinh nghim th khng b nh hng bi nhng s thay i trong
ng h h thng. y l ging nh nhng quy tc m ng dng vo tham s timeout
ti KeWaitXxx.

Gi tr tr li t KeSetTimer, nu TRUE , ch bo rng thit b bm gi l m xung


(trong trng hp no, s gi ca chng ta ti KeSetTimer hy b n v bt u s
m khp ni ln na).

Vo bt k thi gian no bn c th xc nh trng thi hin thi ca mt thi gianr:

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

BOOLEAN counting = KeReadStateTimer(timer);

KeInitializeTimer v nhng chc nng dch v tht s c hn KeSetTimerare m


c b bi nhng chc nng mi hn. Chng ti c th khi to thit b bm gi
vi s gi ny:

ASSERT(KeGetCurrentIqrl() <= DISPATCH_LEVEL);

KeInitializeTimerEx(timer, NotificationTimer);

Chng ti c th cng s dng phin bn m rng ca chc nng thit b bm gi tp


hp,KeSetTimerEx:

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

132/369
LARGE_INTEGER duetime;

BOOLEAN wascounting = KeSetTimerEx(timer, duetime, 0, NULL);

Ti s gii thch xa hn na trong chng ny mc ch ca nhng tham s thm trong


nhng phin bn m rng ny ca cng tc vn hnh.

Mt ln thit b bm gi l s m xung, n l s yn tnh c xem xt not-signaled


cho n khi thi gian n hn xc nh n. Ti im , i tng tr nn c bo
hiu, v tt c cc lung ch i u c gii phng. Nhng bo m h thng duy nht
s ht hn ca thit b bm gi s c ch khng c sm hn thi gian n hn bn
ch nh. Phi chng bn ch r mt thi gian n hn vi mt l tinh luyn chnh xc
so vi ht ca thit b bm gi h thng ( Bn khng c th iu khin), timeout s
c ch sau chc lt chnh xc bn ch r. Bn c th gi KeQueryTimeIncrement
xc nh ht ca ng h h thng.

Nhng thit b bm gi Thng bo c s dng vi mt DPC (Notification Timers


Used with a DPC):

Trong kch bn ny, chng ti mun s ht hn ca thit b bm gi thc y mt DPC.


Bn chn phng php ny ca thao tc nu bn mun c chc chn rng bn c th
gip timeout khng vn mc u tin g c c lung ca cc bn. (T bn c th
ch i di DISPATCH_LEVEL, vic chim li iu khin ca CPU sau thit b bm
gi ht hn ty thuc vo nhng tnh bt bnh thng ca s lp lch lung. Tuy nhin,
DPC thc hin ti IRQL cao v do c hiu qu chn trc tt c cc lung.)

Chng ti khi to i tng thit b bm gi trong cng cch. Chng ti cng khi
to mt i tng KDPC m ci chng ti cp pht nh s trang k c. Chng hn:

PKDPC dpc; // <== points to KDPC you've allocated

ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

KeInitializeTimer(timer);

KeInitializeDpc(dpc, DpcRoutine, context);

Bn c th khi to i tng thit b bm gi bng cch s dng hoc


KeInitializeTimer hoc KeInitializeTimerEx , n khi bn vui lng. DpcRoutine l a
ch ca mt s gi th tc c hon li thng l, iu ny bt buc nh s trang k
c. Tham s vn cnh l mt gi tr 32-bit ty ( kiu nh mt PVOID ) m s c i
qua nh mt i s ti th tc DPC. i s dpc l mt con tr ti mt i tng KDPC
m cho ci bn cung cp c nh s trang lu tr. (N c l trong m rng thit
b ca cc bn, chng hn.)

133/369
Khi chng ti mun bt u s m thit b bm gi xung, chng ti ch r i tng
DPC nh mt trong nhng i s ti KeSetTimer HayKeSetTimerEx:

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

LARGE_INTEGER duetime;

BOOLEAN wascounting = KeSetTimer(timer, duetime, dpc);

Bn c th cng s dng mu KeSetTimerEx m rng nu bn mun. S khc nhau


duy nht gia s gi ny v ci chng ti kho st trong mc c trc l iu chng
ti c ch r a ch i tng DPC nh mt i s. Khi thit b bm gi ht hn, h
thng s xp hng DPC cho s thc hin sm nh cho php nhng iu kin. iu ny
t nht sm nh l bn c kh nng tnh dy t mt s ch i. Th tc DPC ca cc
bn c hnh thc khung sau y:

VOID DpcRoutine(PKDPC dpc, PVOID context, PVOID junk1,

PVOID junk2)

Cho ci g ng gi ca n, thm ch khi bn cung cp mt i s DPC ti KeSetTimer


hay KeSetTimerEx , bn c th vn cn gi l KeWaitXxx i PASSIVE_LEVEL
hay APC_LEVEL nu bn mun. Trn mt CPU h thng- n, DPC xut hin trc
khi s ch i c th kt thc v n thc hin mt IRQL bc cao.

Nhng thit b bm gi ng b ha (Synchronization Timers):

Cng nh nhng i tng s kin, nhng i tng thit b bm gi gi ti c thng


bo ln nhng flavor ng b ha. Mt thit b bm gi thng bo cho php bt k s
no ca vic i nhng lung tin hnh mt khi n ht hn. Mt thit b bm gi
ng b ha, bi s tng phn, ch cho php mt lung n theo ui. Mt ln mt
s ch i ca lung c tha mn, nhng s chuyn i thit b bm gi ti trng thi
not-signaled. to ra mt thit b bm gi ng b ha, bn phi s dng dng m
rng ca chc nng khi to dch v:

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

KeInitializeTimerEx(timer, SynchronizationTimer);

134/369
SynchronizationTimer l mt trong nhng gi tr ca s lit k TIMER_TYPE. Gi tr
khc l NotificationTimer.

Nu bn s dng mt DPC vi mt thit b bm gi ng b ha, ngh rng vic xp


hng DPC nh vic l mt th thm m xy ra khi thit b bm gi ht hn. Ngha l, s
ht hn mang thit b bm gi vo bo hiu trng thi v nhng hng i mt DPC. Mt
lung c th c gii phng khi mt kt qu ca hin thn thit b bm gi bo hiu.

S s dng duy nht ti c bao gi tm thy cho mt thit b bm gi ng b ha khi


bn mun mt thit b bm gi tun hon (xem mc tip theo).

Nhng thit b bm gi Tun hon(Periodic Timers):

Cho n lc ny, ti c bn lun nhng thit b bm gi duy nht m ht hn chnh xc


mt ln. Bng cch s dng chc nng thit b bm gi tp hp m rng bn c th cng
i hi mt timeout tun hon:

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

LARGE_INTEGER duetime;

BOOLEAN wascounting = KeSetTimerEx(timer, duetime,

period, dpc);

Giai on y l theo mt chu k timeout, biu th trong nhng mili-giy (ms), v dpc
l mt con tr chn ti mt i tng KDPC. Mt thit b bm gi ca cch thc ny
ht hn mt ln vo thi gian n hn v nh k sau . t c s ht hn tun
hon chnh xc, ch r cng dng tng quan thi gian vi s tm ngng hot ng.
Vic ch r mt ch s khng vo thi gian gy ra thit b bm gi ngay lp tc ht
hn, v ci hnh vi tun hon bt qua. N thng c ngha bt u mt thit b
bm gi tun hon phi hp vi mt i tng DPC, bi cch, bi v vic cho php bn
c thng bo m khng phi nhiu ln i timeout.

Chc chn gi l KeCancelTimer hy b mt thit b bm gi tun hon trc khi


i tng KTIMER hay th tc DPC bin mt t k c. N l hon ton bi ri cho
h thng chuyn i trnh iu khin ca cc bn v, 10 nan-giy sau , gi th tc
DPC khng tn ti ca cc bn. Khng phi ch iu , nhng n gy ra mt s kim
tra li. Nhng vn ny l khng i g li n cc cu to Driver Verifier lm mt
s kim tra c bit cho k c tr li m cha ng mt KTIMER tch cc.

Mt V d:

135/369
Mt s dng cho nhng thit b bm gi nhn c ch o mt vng kim tra tun t
trong mt lung h thng dnh cho nhim v ca vic nhiu ln kim tra mt thit b
cho hot ng. Khng phi nhiu thit b ngy nay cn c phc v bi mt vng kim
tra tun t, nhng ca bn c th mt ca vi ngoi l. Ti s bn lun ti ny trong
Chng 14, v ni dung bn bao gm mt trnh iu khin mu (POLLING) m minh
ha tt c cc khi nim lin quan. Mt phn m ly mu l vng sau y m thu c
thit b ti nhng khong c nh. Lgic ca trnh iu khin l vng nh vy c
th b t qung bng vic t mt s kin lm cht. Vy th, trnh iu khin s dng
KeWaitForMultipleObjects. M tht s phc tp hn on sau y, ti bin tp son
tho tp trung vo phn lin quan n thit b bm gi:

VOID PollingThreadRoutine(PDEVICE_EXTENSION pdx)

NTSTATUS status;

KTIMER timer;

KeInitializeTimerEx(&timer, SynchronizationTimer);

PVOID pollevents[] = {

(PVOID) &pdx->evKill,

(PVOID) &timer,

};

C_ASSERT(arraysize(pollevents) <= THREAD_WAIT_OBJECTS);

LARGE_INTEGER duetime = {0};

#define POLLING_INTERVAL 500

136/369
KeSetTimerEx(&timer, duetime, POLLING_INTERVAL, NULL);

while (TRUE)

status = KeWaitForMultipleObjects(arraysize(pollevents),

pollevents, WaitAny, Executive, KernelMode, FALSE,

NULL, NULL);

if (status == STATUS_WAIT_0)

break;

if (<device needs attention>)

<do something>;

KeCancelTimer(&timer);

PsTerminateSystemThread(STATUS_SUCCESS);

1. y chng ti khi to mt thit b bm gi kernel. Bn phi ch r mt


SynchronizationTimer y, bi v mt NotificationTimer li bo hiu trng
thi sau s ht hn u tin.
2. Chng ti s cn cung cp mt mng ca nhng con tr i tng thu pht nh
mt trong nhng i s ti KeWaitForMultipleObjects , v y l chng ti
thit lp iu . Phn t u tin ca mng l s kin lm cht m phn khc
no ca trnh iu khin c c l t khi thi gian ca n cho lung h
thng ny thot ra. Phn t th hai l i tng thit b bm gi. S pht
biu C_ASSERT m i theo sau mng ny kim tra rng chng ti c vi
i tng trong mng ca chng ti m chng ti c th tuyt i s dng
mng mc nh ca nhng khi ch i trong i tng lung ca chng ti.

137/369
3. S pht biu KeSetTimerEx bt u mt thit b bm gi tun hon ang chy.
Duetimeis l 0, v vy thit b bm gi i ngay lp tc vo trong bo hiu trng
thi. N s ht hn mi 500 ms sau .
4. Trong khong thi gian kim tra tun t ca chng ti kim sot thnh vng,
chng ti i thit b bm gi ht hn hay cho s kin lm cht s c t.
Nu s ch i hon thnh bi v s kin lm cht, chng ti ri b vng, dn
sch s ln trn, v ra khi lung h thng ny. Nu s ch i hon thnh v
thit b bm gi ht hn, chng ti tip tc bc tip theo.
5. y l trnh iu khin thit b ca chng ti lm ci g lin quan n phn
cng ca chng ti.

Nhng gii php ti nhng thit b bm gi Kernel ( Alternatives to Kernel Timers


)

Hn l s dng mt i tng thit b bm gi kernel, bn c th s dng hai chc nng


tnh ton thi gian khc m c l thch hp hn. u tin ca mi th bn c th gi
KeDelayExecutionThread i PASSIVE_LEVEL cho mt khong cho. Chc
nng ny r rng t cng knh hn so vi to ra, khi to, t, v i mt thit b bm
gi bng cch s dng gi chc nng tch ri.

ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

LARGE_INTEGER duetime;

NSTATUS status = KeDelayExecutionThread(WaitMode,

Alertable, &duetime);

y l WaitMode, s bo ng , v m tnh trng tr v li c cng ngha vi nhng


tham s tng ng ti KeWaitXxx, v duetime l cng loi timestamp m ti tranh lun
trc lin quan n kernel nhng thit b bm gi. Ch rng chc nng ny yu cu
mt con tr ti mt s nguyn ln cho tham s timeout, trong khi m nhng chc nng
khc lin quan n nhng thit b bm gi yu cu chnh s nguyn ln.

Nu yu cu ca cc bn s chm tr trong mt thi gian rt ngn gn (t hn 50 micr-


giy), bn c th gi cho KeStallExecutionProcessorat bt k IRQL no:

KeStallExecutionProcessor(nMicroSeconds);

Mc ch ca s tr hon ny s cho php thi gian phn cng ca cc bn chun b


cho thao tc tip theo ca n trc khi chng trnh ca cc bn tip tc thc hin.
S tr hon c l kt lun mt cch ng k di hn so vi bn i hi bi v
KeStallExecutionProcessorcan c chn trc bi nhng hot ng m xut hin ti
mt IRQL bc cao so vi i tng gi no ang s dng.

138/369
Nhng lung Nhn (Kernel Thread):

i khi l bn s to ra lung kernel-mode ca ring mnh-khi thit b ca cc bn cn


c b xn ngn nh k, chng hn. Trong kch bn ny, bt k s ch i no c
thc hin s trong kernel mode bi v lung chy ch ring trong kernel mode.

X l cc yu cu Plug and Play (Handling Plug and Play Requests):

Ti s cho bn thy trong Chng 6 lm sao x l nhng yu cu vo/ra qun l


PnP gi cch ca cc bn. Vi yu cu nh vy yu cu s dng ng b trn phn ca
cc bn. Ni cch khc, bn i qua chng xung ngn xp trnh iu khin h thp
xung nhng mc v i chng hon thnh. Bn s l i KeWaitForSingleObjectto
gi trong kernel mode bi v qun l PnP gi bn bn trong vn cnh ca mt lung
kernel mode. Ngoi ra, nu bn cn thc hin nhng yu cu ph thuc nh b phn
yu cu x l ca mt PnP-v d, ni v mt thit b USB-bn s ang i trong kernel
mode

X l nhng yu cu vo/ra khc(Handling Other I/O Request):

Khi bn x l nhng loi khc ca nhng yu cu vo/ra v bn bit m bn chy trong


vn cnh ca mt lung khng chuyn quyn m phi a nhng kt qu ca nhng cn
nhc ca cc bn trc khi cch tin hnh n c l d hiu thch hp ngn chn lung
bng vic gi mt nguyn thy ch i. Trong mt trng hp nh vy, bn mun
i trong cng kiu b x l vi thc th m gi bn. Hu ht thi gian, bn c th n
gin tin cy RequestorMode trong IRP bn hin thi x l. Nu bn thu thp cho iu
khin bi nhng cch thc khc vi mt IRP, bn c th gi ExGetPreviousMode
xc nh kiu b x l trc y. Nu bn i i mt thi gian di, n tt hn
s dng kt qu ca nhng s th ny nh i s WaitMode trong KeWaitXxxcall ca
bn, v n cng tt ch r TRUE cho i s cnh bo.

Ghi ch:

Hng cui: Thc hin nhng s ch i khng nhanh nhn tr phi bn bit bn khng
quyt tm.

139/369
Mt s phng php ng b khc (Other Kernel-Mode
Synchronization Primitives )
Nhn XP Windows a ra mt s phng php b sung ng b ha s thc hin
gia nhng lung hay bo v c truy nhp chia s nhng i tng. Trong mc
ny, ti s bn lun mutex nhanh, l mt i tng m nhng xut loi tr ln nhau
nhanh hn s thc hin so vi mt nhn mutex v n ti u ha cho trng hp trong
khng c tht s tranh dnh ang xut hin. Ti cng s m t phm tr ca nhng
chc nng h tr m bao gm t Interlocked trong tn ca chng . Nhng chc nng
ny thc hin nhng thao tc chung nht nh nh tng hoc gim mt s nguyn hay
vic chn hoc loi b mt mc t mt bn k lin kt trong mt cch nguyn t iu
ngn nga giao thoa a nhim hay a x l.

Nhng i tng Mutex nhanh (Fast Mutex Objects):

Mt mutex nhanh thc hin cung cp mt gii php ti mt nhn mutex bo v mt


tit din ti hn ca m. Bng 4-6 tng kt nhng chc nng cng tc bn thng lm
vic vi loi i tng ny.

Bng 4-6. Nhng chc nng


cng tc cho s s dng vi thc
hin Mutexes nhanh
Chc nng dch v M t
Thu nhn quyn s hu ca mutex, i nu cn
ExAcquireFastMutex
thit
Thu nhn quyn s hu ca mutex, i nu cn
ExAcquireFastMutexUnsafe thit, trong hon cnh trong ngi gi v
hiu ha xc nhn ca APCs
ExInitializeFastMutex Khi to i tng mutex
ExReleaseFastMutex Thot khi mutex
Thot khi mutex khng c s truyn ra
ExReleaseFastMutexUnsafe
reenabling APC
Thu nhn mutex nu kh d lm v vy khng
ExTryToAcquireFastMutex
c vic i

So snh vi nhn mutexes, mutexes nhanh c nhng sc mnh v nhng s yu km


c tng kt trong Bng 4-7. Trn cnh du cng, mt mutex nhanh l nhanh nhiu

140/369
hn thu nhn v gii phng nu thc t khng c s tranh chp cho n. Trn
cnh tr, mt lung m thu nhn mt mutex nhanh s khng c kh nng nhn c
nhng kiu nht nh ca s gi th tc khng ng b, ph thuc vo nhng chc nng
chnh xc m bn gi, v s rng buc lm sao bn gi IRPs cho nhng trnh iu khin
khc.

Bng 4-7. So snh Kernel v nhng i


tng Mutex nhanh
Kernel Mutex Fast Mutex
C th c thu nhn mt cch quy
bi mt lung n (h thng bo tr mt Khng th c thu nhn mt cch quy
my m tuyn b)
Mt cch tng i chm Mt cch tng i nhanh hn
Ch nhn khng nhn c chin thng bt
Ch nhn s ch nhn c nhn APCs
k APCs no tr phi bn s dng nhng
" c bit "
chc nng XxxUnsafe
C th b phn ca mt nhiu i tng Khng th c s dng nh mt i s ti
i KeWaitForMultipleObjects

Bt ng, ti liu DDK v nhng i tng mutex nhn lu ni rng nhn a cho
mt quyn u tin s tng ti mt lung m i hi mt mutex. Ti c nhng thng tin
ng tin cy rng iu tht s khng ng t nm 1992 (nm, ngha l, khng phi
Windows xy dng s). Ti liu cng lu ni rng mt lung gi mt mutex khng
th c loi b t s cn bng c thit lp(iu , c chinh phc ti vic cho di
chuyn tt c nhng trang ca n ra khi b nh vt l) y ng khi Windows NT cn
mi m nhng khng ng trong mt thi gian di.

to ra mt mutex nhanh, u tin bn phi cp pht mt cu trc d liu


FAST_MUTEX trong s trang k c. Ri bn khi to i tng bng vic " gi l "
ExInitializeFastMutex, m tht s l mt macro trong WDM.H:

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

ExInitializeFastMutex(FastMutex);

u FastMutex l a ch ca i tng FAST_MUTEX ca cc bn. Mutex bt u


cuc sng trong trng thi khng c ch. thu nhn quyn s hu sau ny, gi l mt
trong s nhng chc nng ny :

ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);

141/369
ExAcquireFastMutex(FastMutex);

or

ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);

ExAcquireFastMutexUnsafe(FastMutex);

Nhng chc nng u tin ny i mutex tr nn sn c, gn quyn s hu ti lung


gi, v sau nng b x l IRQL hin thi ti APC_LEVEL. Vic nng IRQL c
hiu ng ca s kt khi ca tt c APCs. Nhng chc nng th hai ny khng thay i
IRQL.

S b tc kh d khc c th xut hin vi mt trnh iu khin trong ng dn


trang-trong t khc, mt trnh iu khin m c gi gip qun l k c x
l mt li trang. Gi thit bn n gin gi KeEnterCriticalRegion v sau
ExAcquireFastMutexUnsafe. By gi gi thit h thng th thc hin mt kernel-
mode APC c bit trong cng lung, m kh d v KeEnterCriticalRegion khng chn
trc nhn APCs c bit. APC thng l c l nh s trang li, m c l
dn dt ti bn l reentered v b tc vo mt giy th i hi cng mutex. Bn
trnh hon cnh ny bng vic nng IRQL ti APC_LEVEL trc khi thu nhn mutex
trong ch u tin hay, n gin hn, bng cch s dng KeAcquireFastMutex thay v
KeAcquireFastMutexUnsafe. Cng vn c th nu bn s dng mt KMUTEX bnh
thng hay mt s kin ng b ha, tt nhin.

Nu bn khng mun i nu mutex khng ngay lp tc sn c, s s dng " s th


thu nhn " vn hnh:

ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);

BOOLEAN acquired = ExTryToAcquireFastMutex(FastMutex);

Nu gi tr tr li l TRUE, bn by gi s hu mutex. Nu n l FALSE, mt ngi


khc s hu mutex v cn tr bn thu nhn n. gii phng iu khin ca mt
mutex nhanh v cho php lung khc no i hi n, gi cho phin bn chc nng
tng ng i vi cch m bn thu nhn nhanh mutex:

ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);

ExReleaseFastMutex(FastMutex);

or

ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);

142/369
ExReleaseFastMutexUnsafe(FastMutex);

Mt mutex nhanh nhanh bi v s thu nhn v nhng bc phin bn c ti u ha


cho trng hp thng thng trong khng c tranh dnh no cho mutex. Bc ph
bnh trong vic thu nhn mutex ti mt cch nguyn t s gim bt v kim tra nhng
my m s nguyn m ch bo bao nhiu lung hay s hu hay ang i mutex. Nu
s th ch bo khng c lung khc no S hu mutex, khng c cng vic b sung
c yu cu. Nu s th ch bo lung khc m s hu mutex, Nhng khi lung hin
thi trn mt s kin ng b ha l i tng b phn ca FAST_MUTEX. Gii
phng nhng th tp mutex mt cch nguyn t l tng v kim tra my m. Nu s
th ch bo rng khng c lung hin thi ang i, khng c cng vic b sung c
yu cu. Nu lung khc ang i, tuy nhin, ch nhn gi l KeSetEvent gii phng
mt trong nhng ch i.

Interlocked Arithmetic

Bn c th gi cho vi chc nng cng tc trong mt trnh iu khin WDM thc


hin s hc trong mt cch l lung- an ton v b a x l- an ton. (Xem Bng
4-8.) Nhng th tc ny ti hai hng v. Kiu u tin ca th tc c mt tn bt u
vi Interlocked v thc hin mt thao tc nguyn t trong mt cch nh vy m khng
c lung khc no hay CPU c th can thip. Hng v khc cho php mt tn bt u
vi ExInterlocked v s dng mt s kha quay trn.

Bng 4-8. Nhng chc nng dch v cho


kha lng s hc
Chc nng dch v M t
InterlockedCompareExchange So snh v c iu kin trao i
InterlockedDecrement Tr 1 t mt s nguyn
InterlockedExchange Trao i hai gi tr
InterlockedExchangeAdd Thm hai gi tr v tng nhng tr li
InterlockedIncrement Thm 1 vo mt s nguyn
InterlockedOr ORs nhng bit vo trong mt s nguyn
ANDs nhng bit vo trong mt s
InterlockedAnd
nguyn
Exclusive-ORs nhng bit vo trong mt
InterlockedXor
s nguyn
ExInterlockedAddLargeInteger Thm gi tr ti 64- bit s nguyn

143/369
ExInterlockedAddLargeStatistic Thm gi tr vo ULONG
Thm gi tr vo ULONG v gi tr ban
ExInterlockedAddUlong
u nhng tr li
ExInterlockedCompareExchange64 Trao i hai gi tr 64- bit

Nhng chc nng InterlockedXxx c th c gh thm bt k IRQL no; chng cng


c th x l d liu trang PASSIVE_LEVEL v chng khng yu cu mt s kha
quay trn. Mc d nhng th tc ExInterlockedXxx c th c gh thm bt k IRQL
no, h vn hnh trn d liu ch ti hoc trn DISPATCH_LEVEL v bi vy i
hi nh mt s trang l l. L do duy nht s dng mt chc nng ExInterlockedXxx
l nu bn c mt d liu bin thin m bn i khi cn phi tng dn hay gim
bt v i khi cn truy nhp khp c lot no ca nhng ch dn. Bn r rng
i hi s kha quay trn xung quanh nhng s truy nhp nhiu ch dn v s dng
ExInterlockedXxxfunction thc hin nhng s tng dn n gin hay nhng s gim
bt.

Cc chc nng (InterlockedXxx Functions):

InterlockedIncrementadds 1 ti mt s nguyn di trong k c v nhng s tr li gi tr


sau tng dn ti bn:

LONG result = InterlockedIncrement(pLong);

ch Long l a ch ca mt bin c nh my nh mt LONG (iu l, mt s


nguyn di). Nhn thc, thao tc ca chc nng tng ng i vi s tr li pht biu
Long trong C, tr phi s thi hnh khc vi s pht biu n gin cung cp s an
ton lung v s an ton b a x l. InterlockedIncrement m bo rng s nguyn l
s kin gia tng thnh cng nu m trn CPUs khc hay trong nhng lung xng ng
khc trn cng CPU ng thi ang th thay i cng bin. Trong bn cht ca thao tc,
InterlockedIncrement khng m bo rng gi tr n tr li l gi tr ca bin san bng
mt chu k my sau bi nhng lung khc hay CPUs s c kh nng sa i bin
nhanh chng nh thao tc tng dn nguyn t hon thnh.

InterlockedDecrement tng t nh InterlockedIncrement, nhng n tr 1 t bin ch


v tr li gi tr sau gim bt, ging nh cu lnh C tr li Long vi s an ton lung v
s an ton b a x l.

LONG result = InterlockedDecrement(pLong);

You call InterlockedCompareExchange like this:

LONG target;

144/369
LONG result = InterlockedCompareExchange(&target,

newval, oldval);

y ch l mt s nguyn di c dng nh u vo v u ra ti chc nng, oldval


l phng on ca cc bn v ni dung hin thi ca ch, v newval l gi tr mi m
bn mun thit t trong ch nu phng on ca cc bn ng. nhng chc nng thc
hin mt thao tc tng t nh vy c ch bo trong m C sau y nhng phi lm
qua mt thao tc nguyn t l c lung an ton ln b a x l an ton:

LONG CompareExchange(PLONG ptarget, LONG newval, LONG oldval)

LONG value = *ptarget;

if (value == oldval)

*ptarget = newval;

return value;

Ni cch khc, chc nng lun lun tr li gi tr trc y ca bin ch cho bn. Ngoi
ra, nu gi tr trc cn bng vi oldval, n t ch bng newval m bn ch r. Chc
nng s dng mt thao tc nguyn t lm s so snh v s trao i sao cho s thay th
xy ra ch khi bn ng trong phng on ca cc bn v ni dung trc y. Bn cng
c th gi l chc nng InterlockedCompareExchangePointer thc hin mt thao tc
loi so snh- v- trao i tng t vi mt con tr. Chc nng ny cng c nh ngha
nh mt ngi bin tp- bn tnh (Ngha l, mt chc nng cho ngi bin tp no cung
cp mt s thi hnh inline) hay mt chc nng thc s gi, tip tc ph thuc nhng
con tr rng trn nn tng no cho bn bin dch v trn kh nng ca ngi bin tp
pht sinh m inline. Chc nng cui cng trong lp ny l InterlockedExchange , m
n gin s dng mt thao tc nguyn t thay th gi tr ca mt bin s nguyn v
tr li gi tr trc y :

LONG value;

LONG oldval = InterlockedExchange(&value, newval);

Nh bn c l on c, c mt InterlockedExchangePointer m trao i mt gi
tr con tr na (64- bit hay 32-bit, ph thuc trn nn tng). Chc chn nm ch ca
thao tc trao i rnh mt li khi bin tp 64- bit nhng trnh iu khin:

145/369
PIRP Irp = (PIRP) InterlockedExchangePointer(

(PVOID*) &foo, NULL);

InterlockedOr, InterlockedAnd v InterlockedXor mi vi XP DDK. Bn c th s dng


chng trong nhng trnh iu khin m s tip tc chy sm hn nhng phin bn
Windows v chng tht s c thc hin nh nhng hm thuc v chng trnh bin
tp.

Interlocked Fetches v Stores?

Gi thit bn vit sau y v s phn loi m bo v vic truy cp ti mt vi d liu


dng chung:

if (InterlockedExchange(&lock, 42) == 0)

sharedthing++;

lock = 0; // == don't do this

nh ny s thc hin tt trn my tnh Intel x86, ni mi CPU nhn thy k c vit
trong cng mnh lnh. Trn kiu CPU khc, tuy nhin, c th l mt vn .
Mt CPU c l tht s thay i s kha bin thin k c thnh 0 trc khi vic cp
nht k c cho s pht biu tng dn. Hnh vi c th cho php hai CPUs ng thi
truy nhp sharedthing. Vn ny c th xy ra v cch m CPU thc hin nhng
thao tc trong ng song song hay v nhng thi quen trong b iu khin k c. Vy
th, bn cn phi Rework m s dng mt thao tc kha lng cho c hai s thay i
hm li:

if (InterlockedExchange(&lock, 42) == 0)

sharedthing++;

InterlockedExchange(&lock, 0);

146/369
Cc chc nng (ExInterlockedXxx Functions):

Ton b nhng chc nng ExInterlockedXxx yu cu rng bn to ra v khi to mt


s kha quay trn trc khi bn gi l n. Ghi nh rng nhng ton hng ca nhng
chc nng ny phi c mi th trong b nh nonpaged bi v nhng chc nng vn hnh
trn d liu ti IRQL cao.

ExInterlockedAddLargeInteger thm vo nhng s nguyn hai 64- bt v tr li gi tr


trc y ca ch:

LARGE_INTEGER value, increment;

KSPIN_LOCK spinlock;

LARGE_INTEGER prev = ExInterlockedAddLargeInteger(&value,

increment, &spinlock);

Gi tr l ch ca php cng v mt trong nhng ton hng. S tng dn l mt ton


hng s nguyn c thm vo ch. Spinlock l mt s kha quay trn m bn khi to
trc . Gi tr tr li l ch ca gi tr trc khi thm. Ni cch khc, thao tc ca
chc nng ny tng t nh chc nng sau y ch c iu n xut hin di s bo v
ca kha quay trn:

__int64 AddLargeInteger(__int64* pvalue, __int64 increment)

__int64 prev = *pvalue;

*pvalue += increment;

return prev;

Ch rng gi tr tr li l gi tr preaddition, nhng s tng phn no vi s tr li


sau tng dn t InterlockedExchange v nhng chc nng tng t. (ng thi, khng
phi tt c chng trnh bin dch h tr d liu s nguyn __int64, v khng phi tt c
my tnh c th thc hin mt thao tc cng 64- bit s dng nhng ch dn nguyn t.)

ExInterlockedAddUlong tng t i vi s loi tr ExInterlockedAddLargeInteger m


n lm vic vi 32-bit nhng s nguyn khng du:

147/369
ULONG value, increment;

KSPIN_LOCK spinlock;

ULONG prev = ExInterlockedAddUlong(&value, increment, &spinlock);

Chc nng ny cng tr li gi tr preaddition ca ch ca thao tc.

ExInterlockedAddLargeStatistic tng t nh ExInterlockedAddUlongin m n thm


mt gi tr 32- bit ti mt gi tr 64- bit:

VOID ExInterlockedAddLargeStatistic(PLARGE_INTEGER Addend,

ULONG Increment);

Chc nng mi ny nhanh hn ExInterlockedAddUlong v n khng cn tr li gi tr


preincrement ca bin Addend. Bi vy n khng cn thu mt s kha quay trn cho s
ng b ha. Ha tr do chc nng ny cung cp, tuy nhin, ch vi s ch ti nhng
i tng gi khc ca cng chc nng. Ni cch khc, nu bn c m trn mt CPU gi
hng ti ExInterlockedAddLargeStatistic cng lc nh m trn CPU khc ang truy
nhp bin Addend cho c hoc vit, bn c th c nhng kt qu mu thun. Ti c th
gii thch ti sao nh vy bng vic cho bn thy s din t li ny ca s thi hnh Intel
x86 ca chc nng(khng phi m ngun thc t):

mov eax, Addend

mov ecx, Increment

lock add [eax], ecx

lock adc [eax+4], 0

M ny lm vic chnh xc cho nhng mc ch ca incrementing Addend bi v nhng


tin t kha bo m ha tr ca mi thao tc b sung v bi khng mang theo mnh
lnh- thp 32 bt no c th b mt.Gi tr tc thi ca Addend mu 64 lun lun khng
nht qun tuy nhin, bi mt s tng dn c l c thng bng gia ADD v ADC
ti lc ngi no lm mt s sao chp gi tr hon thnh ca mu 64. Bi vy, thm
ch mt i tng gi ca ExInterlocked CompareExchange64 trn CPU khc c th
thu c mt gi tr mu thun.

Initialization

Bn c th khi to nhng danh sch ny nh c cho thy y:

148/369
LIST_ENTRY DoubleHead;

SINGLE_LIST_ENTRY SingleHead;

SLIST_HEADER SListHead;

InitializeListHead(&DoubleHead);

SingleHead.Next = NULL;

ExInitializeSListHead(&SListHead);

ng qun rng bn cng phi cp pht v khi to mt s kha quay trn cho mi danh
sch. Hn na, lu gi cho nhng danh sch u v tt c cc tit mc bn t vo trong
nhng danh sch phi n t vic nh s trang k c bi v nhng th tc h tr thc
hin nhng s truy nhp ca chng ti IRQL cao. Ch rng s quay trn khng c
dng trong vic khi to ca danh sch u v n khng lm bt k ngha no cho
php tranh dnh cho s truy nhp danh sch trc khi danh sch c khi to.

Inserting Items

Bn c th chn nhng tit mc ti u v ui ca gp hai mt bn k lin kt v ti


ci u ca mt n c - bn k lin kt hay mt S-List:

PLIST_ENTRY pdElement, pdPrevHead, pdPrevTail;

PSINGLE_LIST_ENTRY psElement, psPrevHead;

PKSPIN_LOCK spinlock;

pdPrevHead = ExInterlockedInsertHeadList(&DoubleHead,

pdElement, spinlock);

pdPrevTail = ExInterlockedInsertTailList(&DoubleHead,

pdElement, spinlock);

psPrevHead = ExInterlockedPushEntryList(&SingleHead,

psElement, spinlock);

psPrevHead = ExInterlockedPushEntrySList(&SListHead,

149/369
psElement, spinlock);

Nhng gi tr tr li l nhng a ch ca nhng phn t trc ti ci u (hay ci


ui) ca danh sch trong cu hi. Ghi nh nhng a ch phn t m bn s dng vi
nhng chc nng ny l nhng a ch ca nhng cu trc mc vo danh sch m thng
thng nhng trong nhng cu trc ln hn ca cch thc no , v bn s cn s dng
CONTAINING_RECORD v m khi phc a ch ca cu trc ln cn.

Removing Items

Bn c th loi b nhng tit mc t ci u ca bt k danh sch no:

pdElement = ExInterlockedRemoveHeadList(&DoubleHead, spinlock);

psElement = ExInterlockedPopEntryList(&SingleHead, spinlock);

psElement = ExInterlockedPopEntrySList(&SListHead, spinlock);

Nhng gi tr tr li l NULL nu nhng danh sch tng ng trng rng. Chc chn
kim tra gi tr tr li cho NULL trc khi p dng CONTAINING_RECORD v m
phc hi mt con tr cha cu trc.

IRQL Restrictions

Bn c th gi l S - List ch vn hnh trong khi chy ti hoc di


DISPATCH_LEVEL. Nhng chc nng ExInterlockedXxx cho truy nhp gp hai -
c lin kt hay n c- Nhng bn k lin kt c th c gh thm bt k IRQL
no di nh tt c cc s tham kho ti danh sch s dng mt s gi ExInterlockedXxx.
L do khng cho nhng s hn ch IRQL no l nhng s thi hnh ca nhng chc nng
ny v hiu ha nhng ngt, m tng ng nng IRQL ti mc kh d cao nht.
Ch mt ln ngt l lm mt kh nng hot ng, nhng chc nng ny ri thu nhn s
kha quay trn bn c ch r. Khng t m khc no c th kim c iu khin trn
cng CPU, v k t khi khng c m no trn CPU khc c th thu nhn s kha quay
trn, nhng danh sch ca cc bn c bo v.

N hon ho OK cho bn s dng ExInterlockedXxx gi ti s truy nhp mt n


c - lin kt hay gp hai - bn k lin kt ( nhng khng phi mt S -List) trong mt
s phn ca m ca cc bn v s dng khng kha lng vn hnh (InsertHeadList
v vn vn) trong nhng phn khc ca m ca cc bn nu bn i theo sau mt quy tc
n gin. Trc khi s dng mt nguyn thy khng kha lng, thu nhn cng s kha
quay trn m kha vo nhau ca cc bn gi l s s dng. Hn na, hn ch s truy
nhp danh sch ti m chy ti hoc di DISPATCH_LEVEL. Chng hn:

150/369
// Access list using noninterlocked calls:

VOID Function1()

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

KIRQL oldirql;

KeAcquireSpinLock(spinlock, &oldirql);

InsertHeadList(...);

RemoveTailList(...);

KeReleaseSpinLock(spinlock, oldirql);

// Access list using interlocked calls:

VOID Function2()

ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

ExInterlockedInsertTailList(..., spinlock);

Chc nng u tin phi c chy ti hoc di DISPATCH_LEVEL v l mt


yu cu ca gi hng ti KeAcquireSpinLock. L do cho s hn ch IRQL trn nhng
s gi kha lng vo giy vn hnh nh sau: Suppose Function1 thu nhn s kha quay
trn trong s chun b thc hin mt s s truy nhp danh sch Vic thu nhn s
kha quay trn nng IRQL ti DISPATCH_LEVEL. By gi gi thit mt ngt xut
hin trn cng CPU mt bc cao IRQL v nhng s iu chnh tng ch Function2
s dng mt trong nhng th tc ExInterlockedXxx. Nhn by gi s th thu nhn
cng s kha quay trn , v CPU s nh tr hon ton. Vn ny xut hin t vic cho
php m chy ti hai IRQLs khc nhau s dng cng s kha quay trn: Function1

151/369
DISPATCH_LEVEL, v Function2 l ni thc t, d sao i na- HIGH_LEVEL khi
n th mt cch quy thu nhn s kha.

152/369
Bi 13: THC HNH LP TRNH
DRIVER C BN
Thc hnh lp trnh driver c bn
Bi 1

To thit b cng com o - xut hin trong Device Manager

Bi 2

To thit b cng LPT o - xut hin trong Device Manager.

153/369
Bi 14: GI D LIU VO RA
Cc cu trc d liu (Data Structures )
Two data structures are crucial to the handling of I/O requests: the I/O request packet
itself and the IO_STACK_LOCATION structure. Ill describe both structures in this
section.

Structure of an IRP

Figure 5-1 illustrates the IRP data structure, with opaque fields shaded in the usual
convention of this book. A brief description of the important fields follows.

154/369
MdlAddress (PMDL) is the address of a memory descriptor list (MDL) describing
the user-mode buffer associated with this request. The I/O Manager creates this MDL
for IRP_MJ_READ and IRP_MJ_WRITE requests if the topmost device objects flags
indicate DO_DIRECT_IO. It creates an MDL for the output buffer used with an
IRP_MJ_DEVICE_CONTROL request if the control code indicates
METHOD_IN_DIRECT or METHOD_OUT_DIRECT. The MDL itself describes the
user-mode virtual buffer and also contains the physical addresses of locked pages
containing that buffer. A driver has to do additional work, which can be quite minimal,
to actually access the user-mode buffer.

Figure 5-1. I/O request packet data structure.

Flags (ULONG) contains flags that a device driver can read but not directly alter. None
of these flags are relevant to a Windows Driver Model (WDM) driver.

AssociatedIrp (union) is a union of three possible pointers. The alternative that a


typical WDM driver might want to access is named AssociatedIrp.SystemBuffer. The
SystemBuffer pointer holds the address of a data buffer in nonpaged kernel-mode
memory. For IRP_MJ_READ and IRP_MJ_WRITE operations, the I/O Manager
creates this data buffer if the topmost device objects flags specify
DO_BUFFERED_IO. For IRP_MJ_DEVICE_CONTROL operations, the I/O Manager
creates this buffer if the I/O control function code indicates that it should. (See Chapter
9.) The I/O Manager copies data sent by user-mode code to the driver into this buffer
as part of the process of creating the IRP. Such data includes the data involved in a
WriteFile call or the so-called input data for a call to DeviceIoControl. For read requests,
the device driver fills this buffer with data; the I/O Manager later copies the buffer back
to the user-mode buffer. For control operations that specify METHOD_BUFFERED,
the driver places the so-called output data in this buffer, and the I/O Manager copies it
to the user-mode output buffer.

IoStatus (IO_STATUS_BLOCK) is a structure containing two fields that drivers set


when they ultimately complete a request. IoStatus.Status will receive an NTSTATUS
code, while IoStatus.Information is a ULONG_PTR that will receive an information
value whose exact content depends on the type of IRP and the completion status. A
common use of the Information field is to hold the total number of bytes transferred by
an operation such as IRP_MJ_READ that transfers data. Certain Plug and Play (PnP)
requests use this field as a pointer to a structure that you can think of as the answer to a
query.

RequestorMode will equal one of the enumeration constants UserMode or KernelMode,


depending on where the original I/O request originated. Drivers sometimes inspect this
value to know whether to trust some parameters.

155/369
PendingReturned (BOOLEAN) is meaningful in a completion routine and indicates
whether the next lower dispatch routine returned STATUS_PENDING. This chapter
contains a disagreeably long discussion of how to use this flag.

Cancel (BOOLEAN) is TRUE if IoCancelIrp has been called to cancel this request and
FALSE if it hasnt (yet) been called. IRP cancellation is a relatively complex topic that
Ill discuss fully later on in this chapter (in Cancelling I/O Requests).

CancelIrql (KIRQL) is the interrupt request level (IRQL) at which the special cancel
spin lock was acquired. You reference this field in a cancel routine when you release the
spin lock.

CancelRoutine (PDRIVER_CANCEL) is the address of an IRP cancellation routine


in your driver. You use IoSetCancelRoutine to set this field instead of modifying it
directly.

UserBuffer (PVOID) contains the user-mode virtual address of the output buffer for
an IRP_MJ_DEVICE_CONTROL request for which the control code specifies
METHOD_NEITHER. It also holds the user-mode virtual address of the buffer for
read and write requests, but a driver should usually specify one of the device flags
DO_BUFFERED_IO or DO_DIRECT_IO and should therefore not usually need to
access the field for reads or writes. When handling a METHOD_NEITHER control
operation, the driver can create its own MDL using this address.

Tail.Overlay is a structure within a union that contains several members potentially


useful to a WDM driver. Refer to Figure 5-2 for a map of the Tail union. In the
figure, items at the same level as you read left to right are alternatives within a
union, while the vertical dimension portrays successive locations within a structure.
Tail.Overlay.DeviceQueueEntry (KDEVICE_QUEUE_ENTRY) and
Tail.Overlay.DriverContext (PVOID[4]) are alternatives within an unnamed union
within Tail.Overlay. The I/O Manager uses DeviceQueueEntry as a linking field within
the standard queue of requests for a device. The cancel-safe queuing routines IoCsqXxx
use the last entry in the DriverContext array. If these system usages dont get in your
way, at moments when the IRP is not in some queue that uses this field and when you
own the IRP, you can use the four pointers in DriverContext in any way you please.
Tail.Overlay.ListEntry (LIST_ENTRY) is available for you to use as a linking field for
IRPs in any private queue you choose to implement.

CurrentLocation (CHAR) and Tail.Overlay.CurrentStackLocation


(PIO_STACK_LOCATION) arent documented for use by drivers because support
functions such as IoGetCurrentIrpStackLocation can be used instead. During
debugging, however, it might help you to realize that CurrentLocation is the index of
the current I/O stack location and CurrentStackLocation is a pointer to it.

156/369
Figure 5-2. Map of the Tail union in an IRP.

The I/O Stack

Whenever any kernel-mode program creates an IRP, it also creates an associated array
of IO_STACK_LOCATION structures: one stack location for each of the drivers that
will process the IRP and sometimes one more stack location for the use of the originator
of the IRP. (See Figure 5-3.) A stack location contains type codes and parameter
information for the IRP as well as the address of a completion routine. Refer to Figure
5-4 for an illustration of the stack structure.

157/369
Figure 5-3. Parallelism between driver and I/O stacks.

A final consideration in calling the two synchronous IRP routines is that you cant create
just any kind of IRP using these routines. See Table 5-1 for the details. A common trick
for creating another kind of synchronous IRP is to ask for an IRP_MJ_SHUTDOWN,
which has no parameters, and then alter the MajorFunction code in the first stack
location.

Table 5-1. Synchronous IRP


Types
Support Function Types of IRP You Can Create
IRP_MJ_READ IRP_MJ_WRITE
IRP_MJ_FLUSH_BUFFERS
IoBuildSynchronousFsdRequest IRP_MJ_SHUTDOWN IRP_MJ_PNP
IRP_MJ_POWER (but only for
IRP_MN_POWER_SEQUENCE)
IRP_MJ_DEVICE_CONTROL
IoBuildDeviceIoControlRequest
IRP_MJ_INTERNAL_DEVICE_CONTROL

Creating Asynchronous IRPs

The other two IRP creation functionsIoBuildAsynchronousFsdRequest and


IoAllocateIrpcreate an asynchronous IRP. Asynchronous IRPs dont belong to the

158/369
creating thread, and the I/O Manager doesnt schedule an APC and doesnt clean up
when the IRP completes. Consequently:

When a thread terminates, the I/O Manager doesnt try to cancel any
asynchronous IRPs that you happen to have created in that thread.
Its OK to create asynchronous IRPs in an arbitrary or nonarbitrary thread.
Because the I/O Manager doesnt do any cleanup when the IRP completes, you
must provide a completion routine that will release buffers and call IoFreeIrp to
release the memory used by the IRP.
Because the I/O Manager doesnt automatically cancel asynchronous IRPs, you
might have to provide code to do that when you no longer want the operation to
occur.
Because you dont wait for an asynchronous IRP to complete, you can create
and send one at IRQL <= DISPATCH_LEVEL (assuming, that is, that the
driver to which you send the IRP can handle the IRP at elevated IRQLyou
must check the specifications for that driver!). Furthermore, its OK to create
and send an asynchronous IRP while owning a fast mutex.

Refer to Table 5-2 for a list of the types of IRP you can create using the two
asynchronous IRP routines. Note that IoBuildSynchronousFsdRequest and
IoBuildAsynchronousFsdRequest support the same IRP major function codes.

Table 5-2. Asynchronous IRP


Types
Support Function Types of IRP You Can Create
IRP_MJ_READ IRP_MJ_WRITE
IRP_MJ_FLUSH_BUFFERS
IoBuildAsynchronousFsdRequest IRP_MJ_SHUTDOWN IRP_MJ_PNP
IRP_MJ_POWER (but only for
IRP_MN_POWER_SEQUENCE)
Any (but you must initialize the MajorFunction
IoAllocateIrp
field of the first stack location)

IRP-handling scenario numbers 5 and 8 at the end of this chapter contain cookbook
code for using asynchronous IRPs.

Forwarding to a Dispatch Routine

After you create an IRP, you call IoGetNextIrpStackLocation to obtain a pointer to


the first stack location. Then you initialize just that first location. If youve used
IoAllocateIrp to create the IRP, you need to fill in at least the MajorFunction code.

159/369
If youve used another of the four IRP-creation functions, the I/O Manager might
have already done the required initialization. You might then be able to skip this step,
depending on the rules for that particular type of IRP. Having initialized the stack, you
call IoCallDriver to send the IRP to a device driver:

PDEVICE_OBJECT DeviceObject; // <== somebody gives you this

PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);

stack->MajorFunction = IRP_MJ_Xxx;

<other initialization of "stack">NTSTATUS status = IoCallDriver(DeviceObject, Irp);

The first argument to IoCallDriver is the address of a device object that youve obtained
somehow. Often youre sending an IRP to the driver under yours in the PnP stack. In that
case, the DeviceObject in this fragment is the LowerDeviceObject you saved in your
device extension after calling IoAttachDeviceToDeviceStack. Ill describe some other
common ways of locating a device object in a few paragraphs.

The I/O Manager initializes the stack location pointer in the IRP to 1 before the actual
first location. Because the I/O stack is an array of IO_STACK_LOCATION structures,
you can think of the stack pointer as being initialized to point to the -1 element, which
doesnt exist. (In fact, the stack grows from high toward low addresses, but that detail
shouldnt obscure the concept Im trying to describe here.) We therefore ask for the
next stack location when we want to initialize the first one.

What IoCallDriver Does

You can imagine IoCallDriver as looking something like this (but I hasten to add that
this is not a copy of the actual source code):

NTSTATUS IoCallDriver(PDEVICE_OBJECT DeviceObject, PIRP Irp)

IoSetNextIrpStackLocation(Irp);

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

stack->DeviceObject = DeviceObject;

ULONG fcn = stack->MajorFunction;

PDRIVER_OBJECT driver = DeviceObject->DriverObject;

160/369
return (*driver->MajorFunction[fcn])(DeviceObject, Irp);

As you can see, IoCallDriver simply advances the stack pointer and calls the appropriate
dispatch routine in the driver for the target device object. It returns the status code
that that dispatch routine returns. Sometimes I see online help requests wherein people
attribute one or another unfortunate action to IoCallDriver. (For example, IoCallDriver
is returning an error code for my IRP.) As you can see, the real culprit is a dispatch
routine in another driver.

Locating Device Objects

Apart from IoAttachDeviceToDeviceStack, drivers can locate device objects in at least


two ways. Ill tell you here about IoGetDeviceObjectPointer and
IoGetAttachedDeviceReference.

IoGetDeviceObjectPointer

If you know the name of the device object, you can call IoGetDeviceObjectPointer as
shown here:

PUNICODE_STRING devname; // <== somebody gives you this

ACCESS_MASK access; // <== more about this later

PDEVICE_OBJECT DeviceObject;

PFILE_OBJECT FileObject;

NTSTATUS status;

ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

status = IoGetDeviceObjectPointer(devname, access,

&FileObject, &DeviceObject);

This function returns two pointers: one to a FILE_OBJECT and one to a


DEVICE_OBJECT.

To help defeat elevation-of-privilege attacks, specify the most restricted access


consistent with your needs. For example, if youll just be reading data, specify
FILE_READ_DATA.

161/369
When you create an IRP for a target you discover this way, you should set the FileObject
pointer in the first stack location. Furthermore, its a good idea to take an extra reference
to the file object until after IoCallDriver returns. The following fragment illustrates both
these ideas:

PIRP Irp = IoXxx(...);

PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);

ObReferenceObject(FileObject);

stack->FileObject = FileObject;<etc.>

IoCallDriver(DeviceObject, Irp);

ObDereferenceObject(FileObject);

After making this call, dont use either of the file or device object pointers.

IoGetDeviceObjectPointer performs several steps to locate the two pointers that it


returns to you:

1. It uses ZwOpenFile to open a kernel handle to the named device object.


Internally, this will cause the Object Manager to create a file object and to send
an IRP_MJ_CREATE to the target device. ZwOpenFile returns a file handle.
2. It calls ObReferenceObjectByHandle to get the address of the FILE_OBJECT
that the handle represents. This address becomes the FileObject return value.
3. It calls IoGetRelatedDeviceObject to get the address of the DEVICE_OBJECT
to which the file object refers. This address becomes the DeviceObject return
value.
4. It calls ZwClose to close the handle.

Names for Device Objects

For you to use IoGetDeviceObjectPointer, a driver in the stack for the device to which
you want to connect must have named a device object. We studied device object naming
in Chapter 2. Recall that a driver might have specified a name in the \Device folder in
its call to IoCreateDevice, and it might have created one or more symbolic links in the
\DosDevices folder. If you know the name of the device object or one of the symbolic
links, you can use that name in your call to IoGetDeviceObjectPointer.

Mechanically, completing an IRP entails filling in the Status and Information members
within the IRPs IoStatus block and calling IoCompleteRequest. The Status value is
one of the codes defined by manifest constants in the DDK header file NTSTATUS.H.

162/369
Refer to Table 5-3 for an abbreviated list of status codes for common situations. The
Information value depends on what type of IRP youre completing and on whether
youre causing the IRP to succeed or to fail. Most of the time, when youre causing
an IRP to fail (that is, completing it with an error status of some kind), youll set
Information to 0. When you cause an IRP that involves data transfer to succeed, you
ordinarily set the Information field equal to the number of bytes transferred.

Table 5-3. Some Commonly Used


NTSTATUS Codes
Status Code Description
STATUS_SUCCESS Normal completion.
Request failed, but no other status code
STATUS_UNSUCCESSFUL
describes the reason specifically.
STATUS_NOT_IMPLEMENTED A function hasnt been implemented.
An invalid handle was supplied for an -
STATUS_INVALID_HANDLE
operation.
STATUS_INVALID_PARAMETER A parameter is in error.
STATUS_INVALID_DEVICE_REQUEST The request is invalid for this device.
STATUS_END_OF_FILE End-of-file marker reached.
The device is in the process of being
STATUS_DELETE_PENDING
removed from the system.
Not enough system resources (often -
STATUS_INSUFFICIENT_RESOURCES
memory) to perform an operation.

When you call IoCompleteRequest, you supply a priority boost value to be applied to
whichever thread is currently waiting for this request to complete. You normally choose
a boost value that depends on the type of device, as suggested by the manifest constant
names listed in Table 5-4. The priority adjustment improves the throughput of threads
that frequently wait for I/O operations to complete. Events for which the end user is
directly responsible, such as keyboard or mouse operations, result in greater priority
boosts in order to give preference to interactive tasks. Consequently, you want to choose
the boost value with at least some care. Dont use IO_SOUND_INCREMENT for
absolutely every operation a sound card driver finishes, for exampleits not necessary
to apply this extraordinary priority increment to a get-driver-version control request.

Table 5-4. Priority Boost Values for IoCompleteRequest

163/369
Manifest Constant Numeric Priority Boost
IO_NO_INCREMENT 0
IO_CD_ROM_INCREMENT 1
IO_DISK_INCREMENT 1
IO_KEYBOARD_INCREMENT 6
IO_MAILSLOT_INCREMENT 2
IO_MOUSE_INCREMENT 6
IO_NAMED_PIPE_INCREMENT 2
IO_NETWORK_INCREMENT 2
IO_PARALLEL_INCREMENT 1
IO_SERIAL_INCREMENT 2
IO_SOUND_INCREMENT 8
IO_VIDEO_INCREMENT 1

At least one of these three flags must be TRUE. Note that IoSetCompletionRoutine
is a macro, so you want to avoid arguments that generate side effects. The three flag
arguments and the function pointer, in particular, are each referenced twice by the
macro.

IoSetCompletionRoutine installs the completion routine address and context argument


in the nextIO_STACK_LOCATIONthat is, in the stack location in which the next
lower driver will find its parameters. Consequently, the lowest-level driver in a
particular stack of drivers doesnt dare attempt to install a completion routine. Doing so
would be pretty futile, of course, becauseby definition of lowest-level drivertheres
no driver left to pass the request on to.

CAUTION Recall that you are responsible for initializing the next I/O stack location
before you call IoCallDriver. Do this initialization before you install a completion
routine. This step is especially important if you use
IoCopyCurrentIrpStackLocationToNext to initialize the next stack location because that
function clears some flags that IoSetCompletionRoutine sets.

A completion routine looks like this:

NTSTATUS CompletionRoutine(PDEVICE_OBJECT fdo, PIRP Irp,

164/369
PVOID context)

return <some status code>;

It receives pointers to the device object and the IRP, and it also receives whichever
context value you specified in the call to IoSetCompletionRoutine. Completion routines
can be called at DISPATCH_LEVEL in an arbitrary thread context but can also be
called at PASSIVE_LEVEL or APC_LEVEL. To accommodate the worst case
(DISPATCH_LEVEL), completion routines therefore need to be in nonpaged memory
and must call only service functions that are callable at or below DISPATCH_LEVEL.
To accommodate the possibility of being called at a lower IRQL, however, a completion
routine shouldnt call functions such as KeAcquireSpinLockAtDpcLevel that assume
theyre at DISPATCH_LEVEL to start with.

There are really just two possible return values from a completion routine:

STATUS_MORE_PROCESSING_REQUIRED, which aborts the completion


process immediately. The spelling of this status code obscures its actual
purpose, which is to short-circuit the completion of an IRP. Sometimes, a
driver actually does some additional processing on the same IRP. Other times,
the flag just means, Yo, IoCompleteRequest! Like, dont touch this IRP no
more, dude! Future versions of the DDK will therefore define an enumeration
constant, StopCompletion, that is numerically the same as
STATUS_MORE_PROCESSING_REQUIRED but more evocatively named.
(Future printings of this book may also employ better grammar in describing
the meaning to be ascribed the constant, at least if my editors get their way.)
Anything else, which allows the completion process to continue. Because any
value besides STATUS_MORE_PROCESSING_REQUIRED has the same
meaning as any other, I usually just code STATUS_SUCCESS. Future versions
of the DDK will define STATUS_CONTINUE_COMPLETION and an
enumeration constant, ContinueCompletion, that are numerically the same as
STATUS_SUCCESS.

Ill have more to say about these return codes a bit further on in this chapter.

Situation 1: Synchronous Subsidiary IRP

The first situation to consider occurs when you create a synchronous IRP to help you
process an IRP that someone else has sent you. You intend to complete the main IRP
after the subsidiary IRP completes.

165/369
You wouldnt ordinarily use a completion routine with a synchronous IRP, but you
might want to if you were going to implement the safe cancel logic discussed later in this
chapter. If you follow that example, your completion routine will safely return before
you completely finish handling the subsidiary IRP and, therefore, comfortably before
you complete the main IRP. The sender of the main IRP is keeping you in memory until
then. Consequently, you wont need to use IoSetCompletionRoutineEx.

Situation 2: Asynchronous Subsidiary IRP

In this situation, you use an asynchronous subsidiary IRP to help you implement a main
IRP that someone sends you. You complete the main IRP in the completion routine that
youre obliged to install for the subsidiary IRP.

Here you should use IoSetCompletionRoutineEx if its available because the main IRP
senders protection expires as soon as you complete the main IRP. Your completion
routine still has to return to the I/O Manager and therefore needs the protection offered
by this new routine.

Situation 3: IRP Issued from Your Own System Thread

The third situation in our analysis of completion routines occurs when a system thread
youve created (see Chapter 14 for a discussion of system threads) installs completion
routines for IRPs it sends to other drivers. If you create a truly asynchronous IRP
in this situation, use IoSetCompletionRoutineEx to install the obligatory completion
routine and make sure that your driver cant unload before the completion routine
is actually called. You could, for example, claim an IO_REMOVE_LOCK that you
release in the completion routine. If you use scenario 8 from the cookbook at the end
of this chapter to send a nominally asynchronous IRP in a synchronous way, however,
or if you use synchronous IRPs in the first place, theres no particular reason to use
IoSetCompletionRoutineEx because youll presumably wait for these IRPs to finish
before calling PsTerminateSystemThread to end the thread. Some other function in your
driver will be waiting for the thread to terminate before allowing the operating system
to finally unload your driver. This combination of protections makes it safe to use an
ordinary completion routine.

Situation 4: IRP Issued from a Work Item

Here I hope youll be using IoAllocateWorkItem and IoQueueWorkItem, which protect


your driver from being unloaded until the work item callback routine returns. As in
the previous situation, youll want to use IoSetCompletionRoutineEx if you issue an
asynchronous IRP and dont wait (as in scenario 8) for it to finish. Otherwise, you
dont need the new routine unless you somehow return before the IRP completes, which

166/369
would be against all the rules for IRP handling and not just the rules for completion
routines.

Situation 5: Synchronous or Asynchronous IRP for Some Other Purpose

Maybe you have some reason for issuing a synchronous IRP that is not in aid of an IRP
that someone else has sent you and is not issued from the context of your own system
thread or a work item. I confess that I cant think of a circumstance in which youd
actually want to do this, but I think youd basically be toast if you tried. Protecting your
completion routine, if any, probably helps a bit, but theres no bulletproof way for you
to guarantee that youll still be there when IoCallDriver returns. If you think of a way,
youll simply move the problem to after you do whatever it is you think of, at which
point there has to be at least a return instruction that will get executed without protection
from outside your driver.

So dont do this.

167/369
Hng i yu cu Vora (Queuing IO Requests)
Sometimes your driver receives an IRP that it cant handle right away. Rather than reject
the IRP by causing it to fail with an error status, your dispatch routine places the IRP on
a queue. In another part of your driver, you provide logic that removes one IRP from the
queue and passes it to a StartIo routine.

Microsoft Queuing Routines

Apart from this sidebar, Im omitting discussion of the functions IoStartPacket and
IoStartNextPacket, which have been part of Windows NT since the beginning. These
functions implement a queuing model thats inappropriate for WDM drivers. In that
model, a device is in one of three states: idle, busy with an empty queue, or busy
with a nonempty queue. If you call IoStartPacket at a time when the device is idle,
it unconditionally sends the IRP to your StartIo routine. Unfortunately, many times a
WDM driver needs to queue an IRP even though the device is idle. These functions
also rely heavily on a global spin lock whose overuse has created a serious performance
bottleneck.

Just in case you happen to be working on an old driver that uses these obsolete routines,
however, heres how they work. A dispatch routine would queue an IRP like this:

NTSTATUS DispatchSomething(PDEVICE_OBJECT fdo, PIRP Irp)

IoMarkIrpPending(Irp);

IoStartPacket(fdo, Irp, NULL, CancelRoutine);

return STATUS_PENDING;

Your driver would have a single StartIo routine. Your DriverEntry routine would set the
DriverStartIo field of the driver object to point to this routine. If your StartIo routine
completes IRPs, you would also call IoSetStartIoAttributes (in Windows XP or later) to
help prevent excessive recursion into StartIo. IoStartPacket and IoStartNextPacket call
StartIo to process one IRP at a time. In other words, StartIo is the place where the I/O
manager serializes access to your hardware.

168/369
A DPC routine (see the later discussion of how DPC routines work) would complete the
previous IRP and start the next one using this code:

VOID DpcForIsr(PKDPC junk, PDEVICE_OBJECT fdo, PIRP Irp,

PVOID morejunk)

IoCompleteRequest(Irp, STATUS_NO_INCREMENT);

IoStartNextPacket(fdo, TRUE);

To provide for canceling a queued IRP, you would need to write a cancel routine.
Illustrating that and the cancel logic in StartIo is beyond the scope of this book.

In addition, you can rely on the CurrentIrp field of a DEVICE_OBJECT to always


contain NULL or the address of the IRP most recently sent (by IoStartPacket or
IoStartNextPacket) to your StartIo routine.

Queuing an IRP is conceptually very simple. You can provide a list anchor in your
device extension, which you initialize in your AddDevice function:

typedef struct _DEVICE_EXTENSION {

LIST_ENTRY IrpQueue;

BOOLEAN DeviceBusy;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS AddDevice(...)

InitializeListHead(&pdx->IrpQueue);

Then you can write two naive routines for queuing and dequeuing IRPs:

VOID NaiveStartPacket(PDEVICE_EXTENSION pdx, PIRP Irp)

169/369
{

if (pdx->DeviceBusy)

InsertTailList(&pdx->IrpQueue, &Irp->Tail.Overlay.ListEntry);

else

pdx->DeviceBusy = TRUE;

StartIo(pdx->DeviceObject, Irp);

VOID NaiveStartNextPacket(PDEVICE_EXTENSION pdx, PIRP Irp)

if (IsListEmpty(&pdx->IrpQueue))

pdx->DeviceBusy = FALSE;

else

PLIST_ENTRY foo = RemoveHeadList(&pdx->IrpQueue);

PIRP Irp = CONTAINING_RECORD(foo, IRP,

Tail.Overlay.ListEntry);

StartIo(pdx->DeviceObject, Irp);

170/369
Then your dispatch routine calls NaiveStartPacket, and your DPC routine calls
NaiveStartNextPacket in the manner discussed earlier in connection with the standard
model.

There are many problems with this scheme, which is why I called it naive. The most
basic problem is that your DPC routine and multiple instances of your dispatch routine
could all be simultaneously active on different CPUs. They would likely conflict in
trying to access the queue and the busy flag. You could address that problem by creating
a spin lock and using it to guard against the obvious races, as follows:

typedef struct _DEVICE_EXTENSION {

LIST_ENTRY IrpQueue;

KSPIN_LOCK IrpQueueLock;

BOOLEAN DeviceBusy;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS AddDevice(...)

InitializeListHead(&pdx->IrpQueue);

KeInitializeSpinLock(&pdx->IrpQueueLock);

VOID LessNaiveStartPacket(PDEVICE_EXTENSION pdx, PIRP Irp)

KIRQL oldirql;

KeAcquireSpinLock(&pdx->IrpQueueLock, &oldirql);

if (pdx->DeviceBusy)

171/369
InsertTailList(&pdx->IrpQueue, &Irp->Tail.Overlay.ListEntry;

KeReleaseSpinLock(&pdx->IrpQueueLock, oldirql);

else

pdx->DeviceBusy = TRUE;

KeReleaseSpinLock(&pdx->IrpQueueLock, DISPATCH_LEVEL);

StartIo(pdx->DeviceObject, Irp);

KeLowerIrql(oldirql);

VOID LessNaiveStartNextPacket(PDEVICE_EXTENSION pdx, PIRP Irp)

KIRQL oldirql;

KeAcquireSpinLock(&pdx->IrpQueueLock, &oldirql);

if (IsListEmpty(&pdx->IrpQueue)

pdx->DeviceBusy = FALSE;

KeReleaseSpinLock(&pdx->IrpQueueLock, oldirql);

else

PLIST_ENTRY foo = RemoveHeadList(&pdx->IrpQueue);

172/369
KeReleaseSpinLock(&pdx->IrpQueueLock,

DISPATCH_LEVEL);

PIRP Irp = CONTAINING_RECORD(foo, IRP,

Tail.Overlay.ListEntry);

StartIo(pdx->DeviceObject, Irp);

KeLowerIrql(oldirql);

Incidentally, we always want to call StartIo at a single IRQL. Because DPC routines are
among the callers of LessNaiveStartNextPacket, and they run at DISPATCH_LEVEL,
we pick DISPATCH_LEVEL. That means we want to stay at DISPATCH_LEVEL
when we release the spin lock.

(You did remember that these two queue management routines need to be in nonpaged
memory because they run at DISPATCH_LEVEL, right?)

These queueing routines are actually almost OK, but they have one more defect and a
shortcoming. The shortcoming is that we need a way to stall a queue for the duration
of certain PnP and Power states. IRPs accumulate in a stalled queue until someone
unstalls the queue, whereupon the queue manager can resume sending IRPs to a StartIo
routine. The defect in the less naive set of routines is that someone could decide to
cancel an IRP at essentially any time. IRP cancellation complicates IRP queuing logic
so much that Ive devoted the next major section to discussing it. Before we get to that,
though, let me explain how to use the queuing routines that I crafted to deal with all the
problems.

Using the DEVQUEUE Object

To solve a variety of IRP queuing problems, I created a package of subroutines for


managing a queue object that I call a DEVQUEUE. Ill show you first the basic usage of
a DEVQUEUE. Later in this chapter, Ill explain how the major DEVQUEUE service
routines work. Ill discuss in later chapters how your PnP and power management code
interacts with the DEVQUEUE object or objects you define.

173/369
You define a DEVQUEUE object for each queue of requests youll manage in the
driver. For example, if your device manages reads and writes in a single queue, you
define one DEVQUEUE:

typedef struct _DEVICE_EXTENSION {

DEVQUEUE dqReadWrite;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

On the CD Code for the DEVQUEUE is part of GENERIC.SYS. In addition, if you


use my WDMWIZ to create a skeleton driver and dont ask for GENERIC.SYS support,
your skeleton project will include the files DEVQUEUE.CPP and DEVQUEUE.H,
which fully implement exactly the same object. I dont recommend trying to type this
code from the book because the code from the companion content will contain even
more features than I can describe in the book. I also recommend checking my Web site
(www.oneysoft.com) for updates and corrections.

Figure 5-8 illustrates the IRP processing logic for a typical driver using DEVQUEUE
objects. Each DEVQUEUE has its own StartIo routine, which you specify when you
initialize the object in AddDevice:

NTSTATUS AddDevice(...)

PDEVICE_EXTENSION pdx = ...;

InitializeQueue(&pdx->dqReadWrite, StartIo);

174/369
IRP flow with a DEVQUEUE and a StartIo routine.

You can specify a common dispatch function for both IRP_MJ_READ and
IRP_MJ_WRITE:

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,

PUNICODE_STRING RegistryPath)

DriverObject->MajorFunction[IRP_MJ_READ] = DispatchReadWrite;

DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchReadWrite;

#pragma PAGEDCODE

NTSTATUS DispatchReadWrite(PDEVICE_OBJECT fdo, PIRP Irp)

175/369
PAGED_CODE();

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

IoMarkIrpPending(Irp);

StartPacket(&pdx->dqReadWrite, fdo, Irp, CancelRoutine);

return STATUS_PENDING;

#pragma LOCKEDCODE

VOID CancelRoutine(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

CancelRequest(&pdx->dqReadWrite, Irp);

Note that the cancel argument to StartPacket is not optional: you must supply a cancel
routine, but you can see how simple that routine will be.

If you complete IRPs in a DPC routine, youll also call StartNextPacket:

VOID DpcForIsr(PKPDC junk1, PDEVICE_OBJECT fdo, PIRP junk2,

PDEVICE_EXTENSION pdx)

StartNextPacket(&pdx->dqReadWrite, fdo);

176/369
If you complete IRPs in your StartIo routine, schedule a DPC to make the call to
StartNextPacket in order to avoid excessive recursion. For example:

typedef struct _DEVICE_EXTENSION {

KDPC StartNextDpc;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS AddDevice(...)

KeInitializeDpc(&pdx->StartNextDpc,

(PKDEFERRED_ROUTINE) StartNextDpcRoutine, pdx);

VOID StartIo(...)

IoCompleteRequest(...);

KeInsertQueueDpc(&pdx->StartNextDpc, NULL, NULL);

VOID StartNextDpcRoutine(PKDPC junk1, PDEVICE_EXTENSION pdx,

PVOID junk2, PVOID junk3)

StartNextPacket(&pdx->dqReadWrite, pdx->DeviceObject);

In this example, StartIo calls IoCompleteRequest to complete the IRP it has just
handled. Calling StartNextPacket directly might lead to a recursive call to StartIo.
After enough recursive calls, well run out of stack. To avoid the potential stack
overflow, we queue the StartNextDpc DPC object and return. Because StartIo runs
at DISPATCH_LEVEL, it wont be possible for the DPC routine to be called before

177/369
StartIo returns. Therefore, StartNextDpcRoutine can call StartNextPacket without
worrying about recursion.

typedef struct _DEVICE_EXTENSION {

IO_CSQ_IRP_CONTEXT RedContext;

IO_CSQ_IRP_CONTEXT BlueContext;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

When you receive a red IRP, you specify the context structure in your call to
IoCsqInsertIrp:

IoCsqInsertIrp(&pdx->IrpQueue, RedIrp, &pdx->RedContext);

How to park a blue IRP should be pretty obvious.

When you later decide you want to complete a parked IRP, you write code like this:

PIRP RedIrp = IoCsqRemoveIrp(&pdx->IrpQueue, &pdx->RedContext);

if (RedIrp)

RedIrp->IoStatus.Status = STATUS_XXX;

RedIrp->IoStatus.Information = YYY;

IoCompleteRequest(RedIrp, IO_NO_INCREMENT);

IoCsqRemoveIrp will return NULL if the IRP associated with the context structure has
already been cancelled.

Bear in mind the following caveats when using this mechanism:

Its up to you to make sure that you havent previously parked an IRP using a
particular context structure. IoCsqInsertIrp is a VOID function and therefore
has no way to tell you when you violate this rule.

178/369
You mustnt touch an I/O buffer associated with a parked IRP because the IRP
can be cancelled (and the I/O buffer released!) at any time while its parked.
You should remove the IRP from the queue before trying to use a buffer.

179/369
Hy b yu cu vora (Cancelling IO Requests )
Just as happens with people in real life, programs sometimes change their mind about
the I/O requests theyve asked you to perform for them. Were not talking about simple
fickleness here. Applications might terminate after issuing requests that will take a long
time to complete, leaving requests outstanding. Such an occurrence is especially likely
in the WDM world, where the insertion of new hardware might require you to stall
requests while the Configuration Manager rebalances resources or where you might be
told at any moment to power down your device.

To cancel a request in kernel mode, someone calls IoCancelIrp. The operating system
automatically calls IoCancelIrp for every IRP that belongs to a thread thats terminating
with requests still outstanding. A user-mode application can call CancelIo to cancel
all outstanding asynchronous operations issued by a given thread on a file handle.
IoCancelIrp would like to simply complete the IRP its given with
STATUS_CANCELLED, but theres a hitch: IoCancelIrp doesnt know where you have
salted away pointers to the IRP, and it doesnt know for sure whether youre currently
processing the IRP. So it relies on a cancel routine you provide to do most of the work
of cancelling an IRP.

It turns out that a call to IoCancelIrp is more of a suggestion than a demand. It


would be nice if every IRP that somebody tried to cancel really got completed with
STATUS_CANCELLED. But its OK if a driver wants to go ahead and finish the IRP
normally if that can be done relatively quickly. You should provide a way to cancel I/O
requests that might spend significant time waiting in a queue between a dispatch routine
and a StartIo routine. How long is significant is a matter for your own sound judgment;
my advice is to err on the side of providing for cancellation because its not that hard to
do and makes your driver fit better into the operating system.

If It Werent for Multitasking

An intricate synchronization problem is associated with cancelling IRPs. Before I


explain the problem and the solution, I want to describe the way cancellation would
work in a world where there was no multitasking and no concern with multiprocessor
computers. In that utopia, several pieces of the I/O Manager would fit together with your
StartIo routine and with a cancel routine youd provide, as follows:

When you queue an IRP, you set the CancelRoutine pointer in the IRP to the
address of your cancel routine. When you dequeue the IRP, you set
CancelRoutine to NULL.
IoCancelIrp unconditionally sets the Cancel flag in the IRP. Then it checks to
see whether the CancelRoutine pointer in the IRP is NULL. While the IRP is in

180/369
your queue, CancelRoutine will be non-NULL. In this case, IoCancelIrp calls
your cancel routine. Your cancel routine removes the IRP from the queue
where it currently resides and completes the IRP with
STATUS_CANCELLED.
Once you dequeue the IRP, IoCancelIrp finds the CancelRoutine pointer set to
NULL, so it doesnt call your cancel routine. You process the IRP to
completion with reasonable promptness (a concept that calls for engineering
judgment), and it doesnt matter to anyone that you didnt actually cancel the
IRP.

Synchronizing Cancellation

Unfortunately for us as programmers, we write code for a multiprocessing, multitasking


environment in which effects can sometimes appear to precede causes. There are many
possible race conditions between the queue insertion, queue removal, and cancel
routines in the naive scenario I just described. For example, what would happen if
IoCancelIrp called your cancel routine to cancel an IRP that happened to be at the head
of your queue? If you were simultaneously removing an IRP from the queue on another
CPU, you can see that your cancel routine would probably conflict with your queue
removal logic. But this is just the simplest of the possible races.

In earlier times, driver programmers dealt with the cancel races by using a global spin
lockthe cancel spin lock. Because you shouldnt use this spin lock for synchronization
in your own driver, Ive explained it briefly in the sidebar. Read the sidebar for its
historical perspective, but dont plan to use this lock.

Here is a sketch of IoCancelIrp. You need to know this to correctly write IRP-handling
code. (This isnt a copy of the Windows XP source codeits an abridged excerpt.)

BOOLEAN IoCancelIrp(PIRP Irp)

IoAcquireCancelSpinLock(&Irp->CancelIrql);

Irp->Cancel = TRUE;

PDRIVER_CANCEL CancelRoutine = IoSetCancelRoutine(Irp, NULL);

if (CancelRoutine)

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

181/369
(*CancelRoutine)(stack->DeviceObject, Irp);

return TRUE;

else

IoReleaseCancelSpinLock(Irp->CancelIrql);

return FALSE;

1. IoCancelIrp first acquires the global cancel spin lock. As you know if you read
the sidebar earlier, lots of old drivers contend for the use of this lock in their
normal IRP-handling path. New drivers hold this lock only briefly while
handling the cancellation of an IRP.
2. Setting the Cancel flag to TRUE alerts any interested party that IoCancelIrp has
been called for this IRP.
3. IoSetCancelRoutine performs an interlocked exchange to simultaneously
retrieve the existing CancelRoutine pointer and set the field to NULL in one
atomic operation.
4. IoCancelIrp calls the cancel routine, if there is one, without first releasing the
global cancel spin lock. The cancel routine must release the lock! Note also that
the device object argument to the cancel routine comes from the current stack
location, where IoCallDriver is supposed to have left it.
5. If there is no cancel routine, IoCancelIrp itself releases the global cancel spin
lock. Good idea, huh?
Could someone call IoCancelIrp twice? The thing to think about is that the
Cancel flag might be set in an IRP because of some number of primeval calls to
IoCancelIrp and that someone might call IoCancelIrp one more time (getting a
little impatient, are we?) while StartPacket is active. This wouldnt matter
because our first test of the Cancel flag occurs after we install our cancel
pointer. We would find the flag set to TRUE in this hypothetical situation and
would therefore execute the second call to IoSetCancelRoutine. Either
IoCancelIrp or we win the race to reset the cancel pointer to NULL, and
whoever wins ends up completing the IRP. The residue from the primeval calls
is simply irrelevant.

182/369
Cancelling IRPs You Create or Handle

Sometimes youll want to cancel an IRP that youve created or passed to another driver.
Great care is required to avoid an obscure, low-probability problem. Just for the sake of
illustration, suppose you want to impose an overall 5-second timeout on a synchronous
I/O operation. If the time period elapses, you want to cancel the operation. Here is some
naive code that, you might suppose, would execute this plan:

SomeFunction()

KEVENT event;

IO_STATUS_BLOCK iosb;

KeInitializeEvent(&event, ...);

PIRP Irp = IoBuildSynchronousFsdRequest(..., &event, &iosb);

NTSTATUS status = IoCallDriver(DeviceObject, Irp);

if (status == STATUS_PENDING)

LARGE_INTEGER timeout;

timeout.QuadPart = -5 * 10000000;

if (KeWaitForSingleObject(&event, Executive, KernelMode,

FALSE, &timeout) == STATUS_TIMEOUT)

IoCancelIrp(Irp); // <== don't do this!

KeWaitForSingleObject(&event, Executive, KernelMode,

FALSE, NULL);

183/369
}

The first call (A) to KeWaitForSingleObject waits until one of two things happens. First,
someone might complete the IRP, and the I/O Managers cleanup code will then run and
signal event.

Alternatively, the timeout might expire before anyone completes the IRP. In this case,
KeWaitForSingleObject will return STATUS_TIMEOUT. The IRP should now be
completed quite soon in one of two paths. The first completion path is taken when
whoever was processing the IRP was really just about done when the timeout happened
and has, therefore, already called (or will shortly call) IoCompleteRequest. The other
completion path is through the cancel routine that, we must assume, the lower driver
has installed. That cancel routine should complete the IRP. Recall that we have to trust
other kernel-mode components to do their jobs, so we have to rely on whomever we sent
the IRP to complete it soon. Whichever path is taken, the I/O Managers completion
logic will set event and store the IRPs ending status in iosb. The second call (B) to
KeWaitForSingleObject makes sure that the event and iosb objects dont pass out of
scope too soon. Without that second call, we might return from this function, thereby
effectively deleting event and iosb. The I/O Manager might then end up walking on
memory that belongs to some other subroutine.

The problem with the preceding code is truly minuscule. Imagine that someone manages
to call IoCompleteRequest for this IRP right around the same time we decide to cancel
it by calling IoCancelIrp. Maybe the operation finishes shortly after the 5-second
timeout terminates the first KeWaitForSingleObject, for example. IoCompleteRequest
initiates a process that finishes with a call to IoFreeIrp. If the call to IoFreeIrp were
to happen before IoCancelIrp was done mucking about with the IRP, you can see
that IoCancelIrp could inadvertently corrupt memory when it touched the CancelIrql,
Cancel, and CancelRoutine fields of the IRP. Its also possible, depending on the exact
sequence of events, for IoCancelIrp to call a cancel routine, just before someone clears
the CancelRoutine pointer in preparation for completing the IRP, and for the cancel
routine to be in a race with the completion process.

Its very unlikely that the scenario I just described will happen. But, as someone (James
Thurber?) once said in connection with the chances of being eaten by a tiger on Main
Street (one in a million, as I recall), Once is enough. This kind of bug is almost
impossible to find, so you want to prevent it if you can. Ill show you two ways of
cancelling your own IRPs. One way is appropriate for synchronous IRPs, the other for
asynchronous IRPs.

Dont Do This

184/369
A once common but now deprecated technique for avoiding the tiger-on-main-street
bug described in the text relies on the fact that, in earlier versions of Windows, the call
to IoFreeIrp happened in the context of an APC in the thread that originates the IRP.
You could make sure you were in that same thread, raise IRQL to APC_LEVEL, check
whether the IRP had been completed yet, and (if not) call IoCancelIrp. You could be
sure of blocking the APC and the problematic call to IoFreeIrp.

You shouldnt rely on future releases of Windows always using an APC to perform the
cleanup for a synchronous IRP. Consequently, you shouldnt rely on boosting IRQL to
APC_LEVEL as a way to avoid a race between IoCancelIrp and IoFreeIrp.

Cancelling Your Own Synchronous IRP

Refer to the example in the preceding section, which illustrates a function that creates
a synchronous IRP, sends it to another driver, and then wants to wait no longer than
5 seconds for the IRP to complete. The key thing we need to accomplish in a solution
to the race between IoFreeIrp and IoCancelIrp is to prevent the call to IoFreeIrp
from happening until after any possible call to IoCancelIrp. We do this by means of
a completion routine that returns STATUS_MORE_PROCESSING_REQUIRED, as
follows:

SomeFunction()

KEVENT event;

IO_STATUS_BLOCK iosb;

KeInitializeEvent(&event, ...);

PIRP Irp = IoBuildSynchronousFsdRequest(..., &event, &iosb);

IoSetCompletionRoutine(Irp, OnComplete, (PVOID) &event,

TRUE, TRUE, TRUE);

NTSTATUS status = IoCallDriver(...);

if (status == STATUS_PENDING)

LARGE_INTEGER timeout;

185/369
timeout.QuadPart = -5 * 10000000;

if (KeWaitForSingleObject(&event, Executive, KernelMode,

FALSE, &timeout) == STATUS_TIMEOUT)

IoCancelIrp(Irp); // <== okay in this context

KeWaitForSingleObject(&event, Executive, KernelMode,

FALSE, NULL);

IoCompleteRequest(Irp, IO_NO_INCREMENT);

NTSTATUS OnComplete(PDEVICE_OBJECT junk, PIRP Irp, PVOID pev)

if (Irp->PendingReturned)

KeSetEvent((PKEVENT) pev, IO_NO_INCREMENT, FALSE);

return STATUS_MORE_PROCESSING_REQUIRED;

The new code in boldface prevents the race. Suppose IoCallDriver returns
STATUS_PENDING. In a normal case, the operation will complete normally, and a
lower-level driver will call IoCompleteRequest. Our completion routine gains control
and signals the event on which our mainline is waiting. Because the completion routine
returns STATUS_MORE_PROCESSING_REQUIRED, IoCompleteRequest will then
stop working on this IRP. We eventually regain control in our SomeFunction and notice
that our wait (the one labeled A) terminated normally. The IRP hasnt yet been cleaned
up, though, so we need to call IoCompleteRequesta second time to trigger the normal
cleanup mechanism.

186/369
Now suppose we decide we want to cancel the IRP and that Thurbers tiger is loose
so we have to worry about a call to IoFreeIrp releasing the IRP out from under
us. Our first wait (labeled A) finishes with STATUS_TIMEOUT, so we perform a
second wait (labeled B). Our completion routine sets the event on which were waiting.
It will also prevent the cleanup mechanism from running by returning
STATUS_MORE_PROCESSING_REQUIRED. IoCancelIrp can stomp away to its
hearts content on our hapless IRP without causing any harm. The IRP cant be released
until the second call to IoCompleteRequest from our mainline, and that cant happen
until IoCancelIrp has safely returned.

Notice that the completion routine in this example calls KeSetEvent only when the
IRPs PendingReturned flag is set to indicate that the lower drivers dispatch routine
returned STATUS_PENDING. Making this step conditional is an optimization that
avoids the potentially expensive step of setting the event when SomeFunction wont be
waiting on the event in the first place.

I want to mention one last fine point in connection with the preceding code. The call to
IoCompleteRequest at the very end of the subroutine will trigger a process that includes
setting event and iosb so long as the IRP originally completed with a success status.
In the first edition, I had an additional call to KeWaitForSingleObject at this point to
make sure that event and iosb could not pass out of scope before the I/O Manager was
done touching them. A reviewer pointed out that the routine that references event and
iosb will already have run by the time IoCompleteRequest returns; consequently, the
additional wait is not needed.

Cancelling Your Own Asynchronous IRP

To safely cancel an IRP that youve created with IoAllocateIrp or


IoBuildAsynchronousFsdRequest, you can follow this general plan. First define a
couple of extra fields in your device extension structure:

typedef struct _DEVICE_EXTENSION {

PIRP TheIrp;

ULONG CancelFlag;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

Initialize these fields just before you call IoCallDriver to launch the IRP:

pdx->TheIrp = IRP;

pdx->CancelFlag = 0;

187/369
IoSetCompletionRoutine(Irp,

(PIO_COMPLETION_ROUTINE) CompletionRoutine,

(PVOID) pdx, TRUE, TRUE, TRUE);

IoCallDriver(..., Irp);

If you decide later on that you want to cancel this IRP, do something like the following:

VOID CancelTheIrp(PDEVICE_EXENSION pdx)

PIRP Irp =

(PIRP) InterlockedExchangePointer((PVOID*)&pdx->TheIrp, NULL);

if (Irp)

IoCancelIrp(Irp);

if (InterlockedExchange(&pdx->CancelFlag, 1)

IoFreeIrp(Irp);

This function dovetails with the completion routine you install for the IRP:

NTSTATUS CompletionRoutine(PDEVICE_OBJECT junk, PIRP Irp,

PDEVICE_EXTENSION pdx)

if (InterlockedExchangePointer(&pdx->TheIrp, NULL)

InterlockedExchange(&pdx->CancelFlag, 1))

188/369
IoFreeIrp(Irp);

return STATUS_MORE_PROCESSING_REQUIRED;

The basic idea underlying this deceptively simple code is that whichever routine sees
the IRP last (either CompletionRoutine or CancelTheIrp) will make the requisite call to
IoFreeIrp, at point 3 or 6. Heres how it works:

The normal case occurs when you dont ever try to cancel the IRP. Whoever
you sent the IRP to eventually completes it, and your completion routine gets
control. The first InterlockedExchangePointer (point 4) returns the non-NULL
address of the IRP. Since this is not 0, the compiler short-circuits the evaluation
of the Boolean expression and executes the call to IoFreeIrp. Any subsequent
call to CancelTheIrp will find the IRP pointer set to NULL at point 1 and wont
do anything else.
Another easy case to analyze occurs when CancelTheIrp is called long before
anyone gets around to completing this IRP, which means that we dont have
any actual race. At point 1, we nullify the TheIrp pointer. Because the IRP
pointer was previously not NULL, we go ahead and call IoCancelIrp. In this
situation, our call to IoCancelIrp will cause somebody to complete the IRP
reasonably soon, and our completion routine runs. It sees TheIrp as NULL and
goes on to evaluate the second half of the Boolean expression. Whoever
executes the InterlockedExchange on CancelFlag first will get back 0 and skip
calling IoFreeIrp. Whoever executes it second will get back 1 and will call
IoFreeIrp.
Now for the case we were worried about: suppose someone is completing the
IRP right about the time CancelTheIrp wants to cancel it. The worst that can
happen is that our completion routine runs before we manage to call
IoCancelIrp. The completion routine sees TheIrp as NULL and therefore
exchanges CancelFlag with 1. Just as in the previous case, the routine will get 0
as the return value and skip the IoFreeIrp call. IoCancelIrp can safely operate
on the IRP. (It will presumably just return without calling a cancel routine
because whoever completed this IRP will undoubtedly have set the Cancel-
Routine pointer to NULL first.)

The appealing thing about the technique I just showed you is its elegance: we rely
solely on interlocked operations and therefore dont need any potentially expensive
synchronization primitives.

Cancelling Someone Elses IRP

189/369
To round out our discussion of IRP cancellation, suppose someone sends you an IRP
that you then forward to another driver. Situations might arise where youd like to cancel
that IRP. For example, perhaps you need that IRP out of the way so you can proceed
with a power-down operation. Or perhaps youre waiting synchronously for the IRP to
finish and youd like to impose a timeout as in the first example of this section.

To avoid the IoCancelIrp/IoFreeIrp race, you need to have your own completion routine
in place. The details of the coding then depend on whether youre waiting for the IRP.

Canceling Someone Elses IRP on Which Youre Waiting

Suppose your dispatch function passes down an IRP and waits synchronously for it to
complete. (See usage scenario 7 at the end of this chapter for the cookbook version.)
Use code like this to cancel the IRP if it doesnt finish quickly enough to suit you:

NTSTATUS DispatchSomething(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

KEVENT event;

KeInitializeEvent(&event, NotificationEvent, FALSE);

IoSetCompletionRoutine(Irp, OnComplete, (PVOID) &event,

TRUE, TRUE, TRUE);

NTSTATUS status = IoCallDriver(...);

if (status == STATUS_PENDING)

LARGE_INTEGER timeout;

timeout.QuadPart = -5 * 10000000;

if (KeWaitForSingleObject(&event, Executive, KernelMode,

FALSE, &timeout) == STATUS_TIMEOUT)

190/369
{

IoCancelIrp(Irp);

KeWaitForSingleObject(&event, Executive, KernelMode,

FALSE, NULL);

status = Irp->IoStatus.Status;

IoCompleteRequest(Irp, IO_NO_INCREMENT);

return status;

NTSTATUS OnComplete(PDEVICE_OBJECT junk, PIRP Irp, PVOID pev)

if (Irp->PendingReturned)

KeSetEvent((PKEVENT) pev, IO_NO_INCREMENT, FALSE);

return STATUS_MORE_PROCESSING_REQUIRED;

This code is almost the same as what I showed earlier for canceling your own
synchronous IRP. The only difference is that this example involves a dispatch routine,
which must return a status code. As in the earlier example, we install our own
completion routine to prevent the completion process from running to its ultimate
conclusion before we get past the point where we might call IoCancelIrp.

You might notice that I didnt say anything about whether the IRP itself was
synchronous or asynchronous. This is because the difference between the two types of
IRP only matters to the driver that creates them in the first place. File system drivers
must make distinctions between synchronous and asynchronous IRPs with respect to
how they call the system cache manager, but device drivers dont typically have this
complication. What matters to a lower-level driver is whether its appropriate to block a

191/369
thread in order to handle an IRP synchronously, and that depends on the current IRQL
and whether youre in an arbitrary or a nonarbitrary thread.

Canceling Someone Elses IRP on Which Youre Not Waiting

Suppose youve forwarded somebody elses IRP to another driver, but you werent
planning to wait for it to complete. For whatever reason, you decide later on that youd
like to cancel that IRP.

typedef struct _DEVICE_EXTENSION {

PIRP TheIrp;

ULONG CancelFlag;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS DispatchSomething(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

IoCopyCurrentIrpStackLocationToNext(Irp);

IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnComplete,

(PVOID) pdx,

TRUE, TRUE, TRUE);

pdx->CancelFlag = 0;

pdx->TheIrp = Irp;

IoMarkIrpPending(Irp);

IoCallDriver(pdx->LowerDeviceObject, Irp);

return STATUS_PENDING;

192/369
VOID CancelTheIrp(PDEVICE_EXTENSION pdx)

PIRP Irp = (PIRP) InterlockedExchangePointer(

(PVOID*) &pdx->TheIrp, NULL);

if (Irp)

IoCancelIrp(Irp);

if (InterlockedExchange(&pdx->CancelFlag, 1))

IoCompleteRequest(Irp, IO_NO_INCREMENT);

NTSTATUS OnComplete(PDEVICE_OBJECT fdo, PIRP Irp,

PDEVICE_EXTENSION pdx)

if (InterlockedExchangePointer((PVOID*) &pdx->TheIrp, NULL)

InterlockedExchange(&pdx->CancelFlag, 1))

return STATUS_SUCCESS;

return STATUS_MORE_PROCESSING_REQUIRED;

This code is similar to the code I showed earlier for cancelling your own asynchronous
IRP. Here, however, allowing IoCompleteRequest to finish completing the IRP takes
the place of the call to IoFreeIrp we made when we were dealing with our own IRP.
If the completion routine is last on the scene, it returns STATUS_SUCCESS to allow
IoCompleteRequest to finish completing the IRP. If CancelTheIrp is last on the scene,

193/369
it calls IoCompleteRequest to resume the completion processing that the completion
routine short-circuited by returning STATUS_MORE_PROCESSING_REQUIRED.

One extremely subtle point regarding this example is the call to IoMarkIrpPending in
the dispatch routine. Ordinarily, it would be safe to just do this step conditionally in the
completion routine, but not this time. If we should happen to call CancelTheIrp in the
context of some thread other than the one in which the dispatch routine runs, the pending
flag is needed so that IoCompleteRequest will schedule an APC to clean up the IRP in
the proper thread. The easiest way to make that true is simplealways mark the IRP
pending.

Handling IRP_MJ_CLEANUP

Closely allied to the subject of IRP cancellation is the I/O request with the major
function code IRP_MJ_CLEANUP. To explain how you should process this request, I
need to give you a little additional background.

When applications and other drivers want to access your device, they first open a
handle to the device. Applications call CreateFile to do this; drivers call ZwCreateFile.
Internally, these functions create a kernel file object and send it to your driver in an
IRP_MJ_CREATE request. When the entity that opened the handle is done accessing
your driver, it will call another function, such as CloseHandle or ZwClose. Internally,
these functions send your driver an IRP_MJ_CLOSE request. Just before sending you
the IRP_MJ_CLOSE, however, the I/O Manager sends you an IRP_MJ_CLEANUP so
that you can cancel any IRPs that belong to the same file object but that are still sitting
in one of your queues. From the perspective of your driver, the one thing all the requests
have in common is that the stack location you receive points to the same file object in
every instance.

Figure 5-10 illustrates your responsibility when you receive IRP_MJ_CLEANUP. You
should run through your queues of IRPs, removing those that are tagged as belonging to
the same file object. You should complete those IRPs with STATUS_CANCELLED.

194/369
Driver responsibility for IRP_MJ_CLEANUP.

File Objects

Ordinarily, just one driver (the function driver, in fact) in a device stack implements
all three of the following requests: IRP_MJ_CREATE, IRP_MJ_CLOSE, and
IRP_MJ_CLEANUP. The I/O Manager creates a file object (a regular kernel object) and
passes it in the I/O stack to the dispatch routines for all three of these IRPs. Anybody
who sends an IRP to a device should have a pointer to the same file object and should
insert that pointer into the I/O stack as well. The driver that handles these three IRPs
acts as the owner of the file object in some sense, in that its the driver thats entitled to
use the FsContext and FsContext2 fields of the object. So your DispatchCreate routine
can put something into one of these context fields for use by other dispatch routines and
for eventual cleanup by your DispatchClose routine.

Its easy to get confused about IRP_MJ_CLEANUP. In fact, programmers who have a
hard time understanding IRP cancellation sometimes decide (incorrectly) to just ignore
this IRP. You need both cancel and cleanup logic in your driver, though:

IRP_MJ_CLEANUP means a handle is being closed. You should purge all the
IRPs that pertain to that handle.
The I/O Manager and other drivers cancel individual IRPs for a variety of
reasons that have nothing to do with closing handles.

195/369
One of the times the I/O Manager cancels IRPs is when a thread terminates.
Threads often terminate because their parent process is terminating, and the I/O
Manager will also automatically close all handles that are still open when a
process terminates. The coincidence between this kind of cancellation and the
automatic handle closing contributes to the incorrect idea that a driver can get
by with support for just one concept.

In this book, Ill show you two ways of painlessly implementing support for
IRP_MJ_CLEANUP, depending on whether youre using one of my DEVQUEUE
objects or one of Microsofts cancel-safe queues.

Cleanup with a DEVQUEUE

If youve used a DEVQUEUE to queue IRPs, your IRP_MJ_DISPATCH_CLEANUP


routine will be astonishingly simple:

NTSTATUS DispatchCleanup(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

PFILE_OBJECT fop = stack->FileObject;

CleanupRequests(&pdx->dqReadWrite, fop,

STATUS_CANCELLED);

return CompleteRequest(Irp, STATUS_SUCCESS, 0);

CleanupRequests will remove all IRPs from the queue that belong to the same file object
and will complete those IRPs with STATUS_CANCELLED. Note that you complete
the IRP_MJ_CLEANUP request itself with STATUS_SUCCESS.

CleanupRequests contains a wealth of detail:

VOID CleanupRequests(PDEVQUEUE pdq, PFILE_OBJECT fop,

196/369
NTSTATUS status)

LIST_ENTRY cancellist;

InitializeListHead(&cancellist);

KIRQL oldirql;

KeAcquireSpinLock(&pdq->lock, &oldirql);

PLIST_ENTRY first = &pdq->head;

PLIST_ENTRY next;

for (next = first->Flink; next != first; )

PIRP Irp = CONTAINING_RECORD(next, IRP,

Tail.Overlay.ListEntry);

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

PLIST_ENTRY current = next;

next = next->Flink;

if (fop && stack->FileObject != fop)

continue;

if (!IoSetCancelRoutine(Irp, NULL))

continue;

RemoveEntryList(current);

InsertTailList(&cancellist, current);

197/369
KeReleaseSpinLock(&pdq->lock, oldirql);

while (!IsListEmpty(&cancellist))

next = RemoveHeadList(&cancellist);

PIRP Irp = CONTAINING_RECORD(next, IRP,

Tail.Overlay.ListEntry);

Irp->IoStatus.Status = status;

IoCompleteRequest(Irp, IO_NO_INCREMENT);

1. Our strategy will be to move the IRPs that need to be cancelled into a private
queue under protection of the queues spin lock. Hence, we initialize the private
queue and acquire the spin lock before doing anything else.
2. This loop traverses the entire queue until we return to the list head. Notice the
absence of a loop increment stepthe third clause in the for statement. Ill
explain in a moment why its desirable to have no loop increment.
3. If were being called to help out with IRP_MJ_CLEANUP, the fop argument is
the address of a file object thats about to be closed. Were supposed to isolate
the IRPs that pertain to the same file object, which requires us to first find the
stack location.
4. If we decide to remove this IRP from the queue, we wont thereafter have an
easy way to find the next IRP in the main queue. We therefore perform the loop
increment step here.
5. This especially clever statement comes to us courtesy of Jamie Hanrahan. We
need to worry that someone might be trying to cancel the IRP that were
currently looking at during this iteration. They could get only as far as the point
where CancelRequest tries to acquire the spin lock. Before getting that far,
however, they necessarily had to execute the statement inside IoCancelIrp that
nullifies the cancel routine pointer. If we find that pointer set to NULL when
we call IoSetCancelRoutine, therefore, we can be sure that someone really is
trying to cancel this IRP. By simply skipping the IRP during this iteration, we
allow the cancel routine to complete it later on.
6. Heres where we take the IRP out of the main queue and put it in the private
queue instead.

198/369
7. Once we finish moving IRPs into the private queue, we can release our spin
lock. Then we cancel all the IRPs we moved.

Cleanup with a Cancel-Safe Queue

To easily clean up IRPs that youve queued by calling IoCsqInsertIrp, simply adopt the
convention that the peek context parameter you use with IoCsqRemoveNextIrp, if not
NULL, will be the address of a FILE_OBJECT. Your IRP_MJ_CANCEL routine will
look like this (compare with the Cancel sample in the DDK):

NTSTATUS DispatchCleanup(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

PFILE_OBJECT fop = stack->FileObject;

PIRP qirp;

while ((qirp = IoCsqRemoveNextIrp(&pdx->csq, fop)))

CompleteRequest(qirp, STATUS_CANCELLED, 0);

return CompleteRequest(Irp, STATUS_SUCCESS, 0);

Implement your PeekNextIrp callback routine this way:

PIRP PeekNextIrp(PIO_CSQ csq, PIRP Irp, PVOID PeekContext)

PDEVICE_EXTENSION pdx = GET_DEVICE_EXTENSION(csq);

PLIST_ENTRY next = Irp ? Irp->Tail.Overlay.ListEntry.Flink

: pdx->IrpQueueAnchor.Flink;

199/369
while (next != &pdx->IrpQueueAnchor)

PIRP NextIrp = CONTAINING_RECORD(next, IRP,

Tail.Overlay.ListEntry);

PIO_STACK_LOCATION stack =

IoGetCurrentIrpStackLocation(NextIrp);

if (!PeekContext (PFILE_OBJECT) PeekContext

== stack->FileObject)

return NextIrp;

next = next->Flink;

return NULL;

200/369
Tm lc cc kch bn x l (SummaryEight IRP-
Handling Scenarios)
Mc d chiu di ca nhng gii thch c trc, s dng IRP tht s hon ton d dng.
Bi s tnh ca ti, ch c tm kch bn mt cch ng k khc nhau thng dng, v m
c yu cu x l nhng kch bn tng i n gin. Trong mc cui cng ny
ca chng ny, Ti tp hp mt s bc tranh v m ly mu gip bn sp xp li
tt c kin thc l thuyt.

Bi v mc ny c d nh khi mt cookbook m bn c th s dng khng c vic


hon ton hiu mi sc thi cui cng, Ti c bao gm nhng s gi ti nhng chc
nng kha loi b m ti s tranh lun chi tit trong Chng 6. Ti cng c s dng
phng php tc k IoSetCompletionRoutine[Ex ] ch bo nhng ch bn nn gi
IoSetCompletionRoutineEx, trong mt h thng u n sn sng, thit t mt s hon
thnh thng l. Ti cng s dng mt phin bn qu ti ca ngi gip th tc
CompleteRequest ca ti m khng thay i IoStatus. Thng tin trong nhng v d ny
v iu ng cho IRP_MJ_PNP v khng phi khng ng cho nhng kiu IRP khc.

Kch bn 1-S Chuyn xung vi hon thnh th tc

Trong kch bn ny, ngi no gi bn mt IRP. Bn sl y IRP ny ti trnh iu


khin thp hn trong ngn xp PnP ca cc bn, v bn s lm s x l sau no trong
mt s hon thnh thng l. Xem hnh 5-11. Chp nhn chin lc ny khi tt c iu
sau l ng:

Ngi no ang gi bn mt IRP (ngc vi bn to ra chnh IRP).


IRP c l n DISPATCH_LEVEL hay trong mt lung chuyn quyn (
V th l bn khng c th lm tr ngi trong khi nhng trnh iu khin thp
hn x l IRP).
S x l sau ca cc bn c th c lm DISPATCH_LEVEL nu cn ( Bi
v nhng th tc hon thnh c l c gi DISPATCH _LEVEL).

201/369
Hnh 5-11. S Chuyn xung vi s hon thnh th tc .

S gi i ca cc bn v nhng th tc hon thnh s c mu thuc v b khung ny:

NTSTATUS DispatchSomething(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);

if (!NT_SUCCESS(status))

return CompleteRequest(Irp, status);

IoCopyCurrentIrpStackLocationToNext(Irp);

IoSetCompletionRoutine(Irp,

(PIO_COMPLETION_ROUTINE) CompletionRoutine,

pdx, TRUE, TRUE, TRUE);

return IoCallDriver(pdx->LowerDeviceObject, Irp);

202/369
}

NTSTATUS CompletionRoutine(PDEVICE_OBJECT fdo, PIRP Irp,

PDEVICE_EXTENSION pdx)

if (Irp->PendingReturned)

IoMarkIrpPending(Irp);

<whatever post processing you wanted to do>

IoReleaseRemoveLock(&pdx->RemoveLock, Irp);

return STATUS_SUCCESS;

Kch bn 2-S Chuyn xung khng c s hon thnh th tc

Trong kch bn ny, ngi no gi bn mt IRP. Bn s chuyn tip IRP ti trnh


iu khin thp hn trong chng PnP ca cc bn, nhng bn khng cn lm bt c ci
g vi IRP. Xem hnh 5-12. Chp nhn chin lc ny, m c th cng c gi " Let
Mikey try it" cch tip cn, khi c hai ca s theo sau true:

Mt ai ang gi bn mt IRP (ngc vi bn to ra chnh IRP).


Bn khng x l IRP ny, tr phi mt trnh iu khin di bn c l
mun ti.

203/369
Hnh 5-12. S Chuyn xung khng c s hon thnh th tc .

Kch bn ny thng c s dng trong mt trnh iu khin lc, m cn phi ng vai


mt ng dn n gin cho mi IRP m n khng c bit cn lc.

Ti khuyn co vit th tc tr gip sau y, m bn c th s dng mi khi bn cn


thu chin lc ny.

NTSTATUS ForwardAndForget(PDEVICE_EXTENSION pdx, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);

if (!NT_SUCCESS(status))

return CompleteRequest(Irp, status);

IoSkipCurrentIrpStackLocation (Irp);

status = IoCallDriver(pdx->LowerDeviceObject, Irp);

IoReleaseRemoveLock(&pdx->RemoveLock, Irp);

204/369
return status;

Kch bn 3- Hon thnh trong th tc gi i

Trong kch bn ny, bn ngay lp tc hon thnh mt IRP m ngi no gi bn.


Xem hnh 5-13. Chp nhn chin lc ny khi:

Mt ai ang gi bn mt IRP (ngc vi bn to ra chnh IRP), v


Bn c th x l IRP ngay lp tc. iu ny l trng hp cho nhiu cch thc
ca nhng yu cu iu khin (IOCTL) vo/ra. Hoc
Ci g r rng sai vi IRP, m trong trng hp gy ra n qun ngay lp
tc c l l th t t nht lm.

Hnh 5-13. Hon thnh trong s lin lc th tc .

S lin lc thur tc ca cc bn c mu thuc v b khung ny:

NTSTATUS DispatchSomething(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

<process the IRP>

Irp->IoStatus.Status = STATUS_XXX;

Irp->IoStatus.Information = YYY;

205/369
IoCompleteRequest(Irp, IO_NO_INCREMENT);

return STATUS_XXX;

Kch bn 4-Hng i cho sau ny x l

Trong kch bn ny, ngi no gi bn mt IRP iu bn khng c th x l ngay


tc th. Bn mang IRP vo mt hng i cho sau ny x l mt th tc StartIo. Xem
Hnh 5-14. Chp nhn chin lc ny khi c hai s theo sau ng:

Ngi no ang gi bn mt IRP (ngc vi bn to ra chnh IRP).


Bn khng bit rng bn c th x l IRP ngay tc th. iu ny thng xuyn
l trng hp cho IRPs m i hi c xp theo th t truy nhp phn cng,
nh nhng s c v vit.

Hnh 5-14. Hng i cho x l sau ny .

Mc du bn c nhiu s la chn, mt cch tiu biu ca s thi hnh kch bn ny suy


ra vic s dng mt DEVQUEUE qun l hng i IRP. Nhng on sau y cho
thy nhng phn khc nhau ca mt trnh iu khin cho mt ngt vo/ra c chng
trnh ha-c iu khin thit b ngt tng tc nh th no. Ch nhng phn c cho
thy trong ch nt m lin quan c bit ti s dng IRP.

typedef struct _DEVICE_EXTENSION {

206/369
DEVQUEUE dqReadWrite;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject,

PDEVICE_OBJECT pdo)

InitializeQueue(&pdx->dqReadWrite, StartIo);

IoInitializeDpcRequest(fdo, (PIO_DPC_ROUTINE) DpcForIsr);

NTSTATUS DispatchReadWrite(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

IoMarkIrpPending(Irp);

StartPacket(&pdx->dqReadWrite, fdo, Irp, CancelRoutine);

return STATUS_PENDING;

VOID CancelRoutine(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

207/369
CancelRequest(&pdx->dqReadWrite, Irp);

VOID StartIo(PDEVICE_OBJECT fdo, PIRP Irp)

BOOLEAN OnInterrupt(PKINTERRUPT junk, PDEVICE_EXTENSION pdx)

PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);

Irp->IoStatus.Status = STATUS_XXX;

Irp->IoStatus.Information = YYY;

IoRequestDpc(pdx->DeviceObject, NULL, pdx);

VOID DpcForIsr(PKDPC junk1, PDEVICE_OBJECT fdo, PIRP junk2,

PDEVICE_EXTENSION pdx)

PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);

StartNextPacket(&pdx->dqReadWrite, fdo);

208/369
IoCompleteRequest(Irp, IO_NO_INCREMENT);

Kch bn 5-IRP Khng ng b ca ring mnh

Trong kch bn ny bn to nn mt IRP khng ng b, bn tip ti trnh iu khin


khc. Xem Hnh 5-15. Chp nhn chin lc ny khi nhng iu kin sau y ng:

Bn cn trnh iu khin khc thc hin mt thao tc trn li ch ca cc


bn.
Hay l bn trong mt lung chuyn quyn ( bn khng quyt tm Block) hay
bn chy DISPATCH_LEVEL (trong trng hp no bn khng c th
block).

Hnh 5-15. IRP khng ng b ca ring mnh .

Bn s c m nh sau trong trnh iu khin ca cc bn. iu ny khng chin thng tt


yu trong mt s lin lc th tc IRP, v i tng thit b ch khng c chin thng
tt yu l tip theo thp hn mt trong ngn xp PnP ca cc bn. Nhn vo ti liu DDK
cho nhng chi tit y v gi IoBuildAsynchronousFsdRequest v IoAllocateIrp nh
th no.

SOMETYPE SomeFunction(PDEVICE_EXTENSION pdx,

PDEVICE_OBJECT DeviceObject)

NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock,

209/369
(PVOID) 42);

if (!NT_SUCCESS(status))

return <status>;

PIRP Irp;

Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_XXX, DeviceObject,

...);

-or-

Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);

PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);

stack->MajorFunction = IRP_MJ_XXX;

<additional initialization)

IoSetCompletionRoutine[Ex]([pdx->DeviceObject,] Irp,

(PIO_COMPLETION_ROUTINE) CompletionRoutine, pdx,

TRUE, TRUE, TRUE);

ObReferenceObject(DeviceObject);

IoCallDriver(DeviceObject, Irp);

ObDereferenceObject(DeviceObject);

210/369
NTSTATUS CompletionRoutine(PDEVICE_OBJECT junk, PIRP Irp,

PDEVICE_EXTENSION pdx)

<IRP cleanup -- see below>

IoFreeIrp(Irp);

IoReleaseRemoveLock(&pdx->RemoveLock, (PVOID) 42);

return STATUS_MORE_PROCESSING_REQUIRED;

Nhng s gi ti IoAcquireRemoveLock v IoReleaseRemoveLock (nhng im c


gn nhn A) ch cn thit nu thit b ti no bn gi IRP ny l LowerDeviceObject
trong ngn xp PnP ca cc bn. 42 l mt nhn chuyn quyn-n l hon ton phc tp
c gng g b s kha sau nhng tn ti IRP, ng nh vy chng ti c th s dng
con tr IRP nh mt nhn g li xy dng.

Nhng s gi ObReferenceObject v ObDereferenceObject m i trc v i theo sau


s gi IoCallDriver (nhng im c gn nhn B) ch cn thit khi no bn s dng
IoGetDeviceObjectPointer thu c con tr DeviceObject v khi s hon thnh tu
tc ( hay ci g n gi) s gii phng s tham kho kt qu ti mt i tng thit b
hay tp tin.

Bn khng c c hai m A v m B-bn c mt tp hp hay khng ci no.

Nu bn s dng IoBuildAsynchronousFsdRequest xy dng mt IRP_MJ_READ


HayIRP _MJ_WRITE, bn c mt vi cleanup tng i phc tp no thc hin
trong s hon thnh th tc.

Cleanup cho DO_DIRECT_IO ch (C leanup for DO_DIRECT_IO Target ):

Nu i tng thit b ch ch bo phng php m DO_DIRECT_IO bn s phi gii


phng nhng danh sch b m t k c m qun l vo/ra cp pht cho b m d liu
ca cc bn:

NTSTATUS CompletionRoutine(...)

211/369
{

PMDL mdl;

while ((mdl = Irp->MdlAddress))

Irp->MdlAddress = mdl->Next;

MmUnlockPages(mdl); // <== only if you earlier

// called MmProbeAndLockPages

IoFreeMdl(mdl);

IoFreeIrp(Irp);

<optional release of remove lock>

return STATUS_MORE_PROCESSING_REQUIRED;

Cleanup cho DO_BUFFERED_IO ch ( Cleanup for DO_BUFFERED_IO Target


):

Nu i tng thit b ch ch bo DO_BUFFERED_IO , qun l vo/ra s to ra mt


b m h thng. S hon thnh th tc ca cc bn v mt l thuyt cn phi sao chp
d liu t b m h thng n b m ca ring mnh v sau gii phng b m h
thng. Khng may, nhng bit c hiu v nhng lnh vc c cn lm iu ny th
khng phi c ly ti liu trong DDK. Li khuyn ca ti trc tip s n gin khng
gi nhng s c v vit ti mt trnh iu khin m s dng b m vo/ra. Thay vo
, gi ZwReadFile hay ZwWriteFile.

Cleanup cho nhng ch khc (C leanup for Other Targets ):

Nu thit b ch ch bo khng DO_DIRECT_IO hay DO_BUFFERED_IO, khng c


cleanup b sung. Phew!

Kch bn 6-IRP ng b ca ring mnh

212/369
Trong kch bn ny bn to nn mt ng b IRP, bn chuyn tip ti trnh iu khin
khc. Xem hnh 5-16. Chp nhn chin lc ny khi tt c s theo sau ng:

Bn cn trnh iu khin khc thc hin mt thao tc trn s i din ca cc


bn.
Bn phi i thao tc hon thnh trc y theo ui.
Bn chy PASSIVE_LEVEL trong mt lung khng chuyn quyn.

Hnh 5-16. IRP ng b ca ring mnh .

Bn s c m nh s theo sau trong trnh iu khin ca) cc bn. iu ny khng chin


thng tt yu trong mt s lin lc th tc IRP, v i tng thit b ch khng c
chin thng tt yu l tip theo thp hn mt trong ngn xp PnP ca cc bn. Nhn
vo ti liu DDK cho nhng chi tit y v gi IoBuildSynchronousFsdRequest v
IoBuildDeviceIoControlRequest nh th no.

SOMETYPE SomeFunction(PDEVICE_EXTENSION pdx,

PDEVICE_OBJECT DeviceObject)

NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock,

213/369
(PVOID) 42);

if (!NT_SUCCESS(status))

return <status>;

PIRP Irp;

KEVENT event;

IO_STATUS_BLOCK iosb;

KeInitializeEvent(&event, NotificationEvent, FALSE);

Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_XXX,

DeviceObject, ..., &event, &iosb);

-or-

Irp = IoBuildDeviceIoControlRequest(IOCTL_XXX, DeviceObject,

..., &event, &iosb);

status = IoCallDriver(DeviceObject, Irp);

if (status == STATUS_PENDING)

KeWaitForSingleObject(&event, Executive, KernelMode,

FALSE, NULL);

status = iosb.Status;

214/369
IoReleaseRemoveLock(&pdx->RemoveLock, (PVOID) 42);

Nh trong kch bn 5, nhng s gi ti IoAcquireRemoveLock v


IoReleaseRemoveLock (nhng im c gn nhn A) ch cn thit nu thit b ti no
bn gi IRP ny l LowerDeviceObject trong ngn xp PnP ca cc bn. 42 l mt nhn
chuyn quyn-n n gin qu phc tp th thu nhn s kha loi b sau tn ti
IRP, ng nh vy chng ti c th s dng con tr IRP nh mt nhn g li xy dng.

Chng ti s s dng kch bn ny thng xuyn trong Chng 12 gi nhng khi


yu cu USB (URBs) ng b xung ngawn xp. Trong nhng v d chng ti s nghin
cu , chng ti s thng ang lm iu ny trong vn cnh ca mt s lin lc th
tc IRP m c lp thu nhn s kha loi b. Bi vy, bn khng chin thng nhn thy
m kha loi b thm trong nhng v d .

Bn khng phi lm qut dn sau khi IRP ny! Qun l vo/ra lm n t ng.

Kch bn 7-S Chuyn qua ng b Xung

In kch bn ny, ngi no gi bn mt IRP. Bn i qua IRP xung ng b trong


ngn xp PnP ca cc bn v sau tip tc x l. Xem hnh 5-17. Chp nhn chin
lc ny khi tt c s theo sau ng:

Ngi no ang gi bn mt IRP (ngc vi bn to ra chnh IRP).


Bn chy PASSIVE_LEVEL trong mt lung khng chuyn quyn.
S x l sau ca cc bn cho IRP phi c lm PASSIVE_LEVEL.

215/369
Hnh 5-17. S chuyn qua ng b xung .

Mt v d tt ca khi no bn cn s dng chin lc ny trong khi ang x l mt


hng v(flavor)IRP_MN_START_DEVICE ca yu cu PnP.

Ti khuyn co vit hai th tc gip lm cho n tr nn d dng thc hin s


chuyn qua ng b ny- thao tc xung:

NTSTATUS ForwardAndWait(PDEVICE_EXTENSION pdx, PIRP Irp)

KEVENT event;

KeInitialize(&event, NotificationRoutine, FALSE);

IoCopyCurrentIrpStackLocationToNext(Irp);

IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)

ForwardAndWaitCompletionRoutine, &event, TRUE, TRUE, TRUE);

NTSTATUS status = IoCallDriver(pdx->LowerDeviceObject, Irp);

if (status == STATUS_PENDING)

KeWaitForSingleObject(&event, Executive, KernelMode,

216/369
FALSE, NULL);

status = Irp->IoStatus.Status;

return status;

NTSTATUS ForwardAndWaitCompletionRoutine(PDEVICE_OBJECT fdo,

PIRP Irp, PKEVENT pev)

if (Irp->PendingReturned)

KeSetEvent(pev, IO_NO_INCREMENT, FALSE);

return STATUS_MORE_PROCESSING_REQUIRED;

Ngi gi th tc ny cn gi cho IoCompleteRequest cho IRP ny v thu nhn v


gii phng s kha loi b. N khng thch hp cho ForwardAndWait cha ng
kha lgic loi b bi v ngi gi c l khng mun gii phng s kha sm nh
vy.

Ch rng chc nng IoForwardIrpSynchronously Windows XP DDK ng gi y


ging nh nhng bc.

Kch bn 8-IRP Khng ng b c x l ng b

In kch bn ny, bn to nn mt IRP khng ng b, bn chuyn tip ti trnh iu


khin khc. Ri bn i IRP hon thnh. Xem hnh 5-18. Chp nhn chin lc ny
khi tt c s theo sau ng:

Bn cn trnh iu khin khc thc hin mt thao tc trn s i din ca cc


bn.
Bn cn i thao tc kt thc trc khi bn c th tip tc.
Bn chy APC_LEVEL trong mt lung khng chuyn quyn.

217/369
Hnh 5-18. IRP khng ng b c x l ng b .

Ti s dng k thut ny khi no ti mc phi mt mutex nhanh thc hin v cn thc


hin mt thao tc ng b. M ca cc bn kt hp nhng phn t bn nhn thy trc
y (so snh vi nhng kch bn 5 v 7):

SOMETYPE SomeFunction(PDEVICE_EXTENSION pdx,

PDEVICE_OBJECT DeviceObject)

NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock,

(PVOID) 42);

if (!NT_SUCCESS(status))

return <status>;

PIRP Irp;

218/369
Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_XXX, DeviceObject,

...);

-or-

Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);

PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);

Stack->MajorFunction = IRP_MJ_XXX;

<additional initialization)

KEVENT event;

KeInitializeEvent(&event, NotificationEvent, FALSE);

IoSetCompletionRoutine[Ex]([pdx->DeviceObject], Irp,

(PIO_COMPLETION_ROUTINE) CompletionRoutine,

&event, TRUE, TRUE, TRUE);

status = IoCallDriver(DeviceObject, Irp);

if (status == STATUS_PENDING)

KeWaitForSingleObject(&event, Executive, KernelMode,

FALSE, NULL);

IoReleaseRemoveLock(&pdx->RemoveLock, (PVOID) 42);

NTSTATUS CompletionRoutine(PDEVICE_OBJECT junk, PIRP Irp,

PKEVENT pev)

219/369
if (Irp->PendingReturned)

KeSetEvent(pev, EVENT_INCREMENT, FALSE);

<IRP cleanup -- see above>

IoFreeIrp(Irp);

return STATUS_MORE_PROCESSING_REQUIRED;

(nhng im c gn nhn A) ch cn thit nu thit b ti bn ang gi IRP ny

Nh trong nhng kch bn trc , nhng s gi ti IoAcquireRemoveLock v


IoReleaseRemoveLock (nhng im c gn nhn A) ch cn thit nu thit b ti
no bn gi IRP ny l LowerDeviceObject trong ngn xp PnP ca cc bn. 42 l mt
nhn chuyn quyn-n n gin qu phc tp th thu nhn s kha loi b sau
tn ti IRP, ng nh vy chng ti c th s dng con tr IRP nh mt nhn g li xy
dng.

Ch rng bn vn cn phi thc hin tt c cng cleanup c bn lun trc v


Qun l vo/ra l khng qut dn sau khi mt IRP khng ng b. Bn c l cng
cn cung cp cho cancelling IRP ny, ti trng hp no bn cn phi s dng k thut
tranh lun trong thn ca chng ny cho IRPs khng ng b cancelling.

220/369
Bi 15: THC HNH LP TRNH
DRIVER CHO X L IRP
Thc hnh mt s bi lp trnh driver c bn
Bi 1.

Lp trnh truyn thng cng com da vo x l IRP.

Bi 2.

Lp trnh truyn thng cng LPT da vo x l IRP

Bi 3.

Lp trnh m rng x l IRP.

221/369
Bi 16: C V GHI D LIU
Cu hnh thit b ca bn (Configuring Your Device )
Trong chng trc, ti tho lun vi bn v IRP-MJ-PNP cho thit b cm v
chy (Plug and Play). IRP_MN_START_DEVICE l mt phng tin cung cp cho
bn cc thng tin v cc ngun vo/ra ci m c ch nh bi PnP Manager bn
s dng. Ti ch cho bn cch t c ng thi list cc cch thc n gin
(cha tinh t) v cch dch cc m t ngun v lm sao c th gi tr gip hm
StartDevice m bn c th thy nguyn mu nh sau:

NTSTATUS StartDevice(PDEVICE_OBJECT fdo,

PCM_PARTIAL_RESOURCE_LIST raw,

PCM_PARTIAL_RESOURCE_LIST translated)

Cc cu trc CM_PARTIAL_RESOURCE_lIST cha ng mt s m v mt mng


cc cu trc CM_PARTIAL_RESOURCE_DESCRIPTOR, nh l minh ho hnh 7.1.
Mi mt k hiu ngun trong mng ny c mt thnh phn l Type biu th kiu
ca ngun c m t v mt s cc thnh phn thm vo ci m cung cp cc th hin
c th v ngun c ch nh. Bn s khng b lm cho ngc nhin (bt ng) bng vic
hy tm trong mng ny v theo cch: Nu thit b ca bn s dng IRQ v vng cc
cng vo ra, bn s nhn c hai k hiu ngun t trong mng ny. Mt trong hai k
hiu l dnh cho IRQ ca bn v k hiu cn li s dnh cho phn cng vo/ra. Tht
khng may, bn khng th d on trc c th t m cc k hiu s xut hin trong
mng ny. Chnh v vy, hm gip StartDevice s phi bt u vi mt vng lp
l tri mng mng ny bng cch trch ra cc gi tr ngun vo mt tp hp cc bin
cc b. Bn c th s dng cc bin cc b ny sau lin kt vi cc ngun ch nh
ti cc v tr mm bn cn (n s khc vi nhng g l thuyt ni, c th khc mt cht
vi cc th t m trong PnP Manager chn la hin th cho bn)

222/369
Hnh 7-1. Structure of a partial resource list.

Vi bn phc tho ny, hm StartDevice s c dng:

NTSTATUS StartDevice(PDEVICE_OBJECT fdo,

PCM_PARTIAL_RESOURCE_LIST raw,

PCM_PARTIAL_RESOURCE_LIST translated)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

PCM_PARTIAL_RESOURCE_DESCRIPTOR resource =

223/369
translated->PartialDescriptors;

ULONG nres = translated->Count;

<local variable declarations>

for (ULONG i = 0; i < nres; ++i, ++resource)

switch (resource->Type)

case CmResourceTypePort:

<save port info in local variables>

break;

case CmResourceTypeInterrupt:

<save interrupt info in local variables>

break;

case CmResourceTypeMemory:

<save memory info in local variables>

break;

case CmResourceTypeDma:

<save DMA info in local variables>

break;

224/369
}

<use local variables to configure driver & hardware> return STATUS_SUCCESS;

1. Ti s s dng con tr trong on code ny ch ra k hiu ngun hin ti vi


di khc nhau ca mng.
2. Thnh phn Count cu danh sch ngun s ch ra rng c bao nhiu k hiu
ngun trong mng PartialDescriptor.
3. Bn nn khai bo cc bin cc b thch hp vi mi ngun vo/ra m bn mun
nhn c. Ti s c th ho nhng iu ny sau khi m ti tho lun v cch
lm th no lin kt (lin h) cc ngun vo ra chun.
4. Cc k hiu ngun trong sut vng lp, bn hy s dng cu trc lnh Switch
lu cc thng tin m t ngun vo cc bin cc b tng ng. Trong on
text ny, ti n nh mt thit b ci m cn s dng mt cng vo/ra v mt
ngt, v thit b s i hi phi tm ra cc kiu d liu ngun
CmResourceTypePort v CmResourceTypeInterup. Ti ang ch cho bn mt
cch k lng v hai kiu d liu ngun chun CmResourceTypeMemory v
CmResourceTypeDma.
5. Mt vng lp bn ngoi, cc bin cc b m bn khi to trong cc nhn khc
nhau s gi cc thng tin ngun bn cn.

Nu bn c nhiu hn mt ngun c kiu ring bit (c th), bn cn phi to ra mt


cch thc no thng bo cho thnh phn cc k hiu ngun. a ra mt v d
c th (nhng ch l tng tng), gi s rng thit b ca bn s dng 4 KB ca vng
nh cho mc ch iu khin v 16 KB vng nh dnh cho vic thu thp d liu. Bn
mong rng s nhn c hai ngun CmResourceTypeMemory t Manager PnP. iu
khin b nh l mt khi c dung lng 4 KB, v b nh d liu l mt khi c dung
lng 16 KB. Nu code (ngun) ca thit b ca bn c s phn bit k t nh l kch c
khc nhau nh trong v d, bn c th ni r n l ci g trong phn ngun (code).

Bng 7.1 th hin ci nhn tng qut v mi kiu d liu ngun.

Table 7-1. Overview of


Processing Steps for I/O
Resources
Resource Type Overview

225/369
Possibly map port range; save base port address in
Port
device extension
Map memory range; save base address in device
Memory
extension
Dma Call IoGetDmaAdapter to create an adapter object
Call IoConnectInterrupt to create an interrupt object
Interrupt
that points to your interrupt service routine (ISR)

226/369
a ch mt B m d liu (Addressing a Data Buffer )
Khi mt ng dng bt u thao tc c hay ghi, n s cung cp mt vng m d liu
thng qua cch cung cp cho b qun l vo/ra mt ch ngi dung a ch o v
chiu di ca n. Nh ti trnh by trong chng 3 trc y, mt nhn iu khin
rt him khi truy xut vo b nh m s dng ch ngi dung vi a ch o bi v,
nhn chung, bn chc chn khng th cht c cc lung. Microsoft Windows XP cung
cp cho bn 3 cch truy xut mt b m d liu ch ngi dung:

1. Trong phng thc Buffered, trnh qun l vo /ra to ra mt b m h thng


bng vi kch thc ca b m d liu ch ngi dung. V bn lm vic
vi b m h thng ny. Trnh qu l vao/ra s gim st cn thn (trng nom)
vic copy d liu gia b m ch ngi dng v b m h thng.
2. Trong phng thc Direct, trnh qun l vo/ra kho cc trang vt l ang cha
ng b m ch ngi dng v to ra mt cu trc d liu ph c gi l
danh sch k hiu b nh (MDL) din t cc trang b kho. Khi bn s
lm vic vi MDL.
3. Phng thc neither, trnh qun l vo ra n gin l cho bn vt qua a ch
a ch ngi dng. Bn cn phi lm vic ht sc cn thn vi a ch ch
ngi dng/

Hnh 7.2 minh ho hai phng thc u. Phng thc cui cng, tt nhin l phng
thc m h thng khng lm g c c th gip bn n gn (ly c) d liu ca
bn.

227/369
Hnh 7-2. Accessing user-mode data buffers.

Ch r mt phng thc vng m (Specifying a Buffering Method):

Bn tin hnh nh r mt phng thc vng m c hay ghi bng cch thit lp cc
bit c trong i tgn thit b ca bn ngay sau khi bn to ra hm AddDivice:

NTSTATUS AddDevice(...)

PDEVICE_OBJECT fdo;

IoCreateDevice(..., &fdo);

fdo->Flags = DO_BUFFERED_IO;

<or>

fdo->Flags = DO_DIRECT_IO;

<or>

fdo->Flags = 0; // i.e., neither direct nor buffered

Bn khng th thay i nh ca mnh v phng thc vng m sau . Cc trnh


iu khin lc c th copy thit lp c ny v s khng c cch no bit c nu
bn thc hin thay i ca mnh v nh ra mt phng thc vng m khc,

Phng thc ca vng m (The Buffered Method):

PVOID uva; // <== user-mode virtual buffer address

ULONG length; // <== length of user-mode buffer

PVOID sva = ExAllocatePoolWithQuota(NonPagedPoolCacheAligned,

length);

if (writing)

RtlCopyMemory(sva, uva, length);

228/369
Irp->AssociatedIrp.SystemBuffer = sva;

PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);

if (reading)

stack->Parameters.Read.Length = length;else

stack->Parameters.Write.Length = length;

<code to send and await IRP>

if (reading)

RtlCopyMemory(uva, sva, length);

ExFreePool(sva);

Phng php trc tip (The Direct Method):

Nu trong i tng thit b bn ch r DO_DIRECT_IO th trnh iu khin vo ra s


to ra mt MDL m t cc trang b kho ang cha vng m d liu ch ngi
dng.Cu trc ca MDL c khai bo nh sau:

typedef struct _MDL {

struct _MDL *Next;

CSHORT Size;

CSHORT MdlFlags;

struct _EPROCESS *Process;

PVOID MappedSystemVa;

PVOID StartVa;

ULONG ByteCount;

ULONG ByteOffset;

} MDL, *PMDL;

229/369
Hnh 7.3 minh ho cho quy lut ca MDL. Thnh phn StartVa cung cp a ch o ca
vng m - ch hp l trong trng hp ch ngi dng x l iu ny. ByteOffset
l a ch offset ca ni bt u vng m trong sut mt Frame, v ByteCount l kch
thc ca vng m tnh theo n v Byte. Mng Page, khng c khai bo thng
thng nh phn cu trc ca MDL, tip theo MDL trong b nh v cha ng s lng
cc trang Frame vt l ca bn a ch o ch ngi dng.

Hnh 7.3. Lit k cu trc k hiu (th hin) ca b nh.

Theo cch ny, chng ta chng bao gi truy cp trc tip ti cc thnh phn ca cu trc
MDL. Chng ta s dng cc Macro v nng cp cc hm nh trong bng 7.2

Table 7-2. Macros and Support


Functions for Accessing an MDL
Macro or Function Description
IoAllocateMdl Creates an MDL.

230/369
Builds an MDL for a subset of an existing
IoBuildPartialMdl
MDL.
IoFreeMdl Destroys an MDL.
Modifies an MDL to describe a region of
MmBuildMdlForNonPagedPool
kernel-mode nonpaged memory.
MmGetMdlByteCount Determines byte size of buffer.
MmGetMdlByteOffset Gets buffer offset within first page.
MmGetMdlPfnArray Locates array of physical page pointers.
MmGetMdlVirtualAddress Gets virtual address.
Creates a kernel-mode virtual address that maps
MmGetSystemAddressForMdl
to the same locations in memory.
Same as MmGetSystemAddressForMdl but
MmGetSystemAddressForMdlSafe
preferred in Windows 2000 and later systems.
(Re)initializes an MDL to describe a given
MmInitializeMdl
virtual buffer.
Creates a kernel-mode virtual address that maps
MmMapLockedPages
to the same locations in memory.
Similar to MmMapLockedPages but preferred
MmMapLockedPagesSpecifyCache
in Windows 2000 and later systems.
MmPrepareMdlForReuse Reinitializes an MDL.
MmProbeAndLockPages Locks pages after verifying address validity.
Determines how much memory would be
needed to create an MDL to describe a given
MmSizeOfMdl virtual buffer. You dont need to call this
routine if you use IoAllocateMdl to create the
MDL in the first place.
MmUnlockPages Unlocks the pages for this MDL.
MmUnmapLockedPages Undoes a previous MmMapLockedPages.

Bn c th hnh dung rng trnh qun l vo/ra thc hin on code nh di y


thc hin phng thc c hoc ghi mt cch trc tip.

KPROCESSOR_MODE mode; // <== either KernelMode or UserMode

231/369
PMDL mdl = IoAllocateMdl(uva, length, FALSE, TRUE, Irp);

MmProbeAndLockPages(mdl, mode,

reading ? IoWriteAccess : IoReadAccess);

<code to send and await IRP>

MmUnlockPages(mdl);

IoFreeMdl(mdl);

u tin, trnh qun l vo/ra to ra mt MDL m t vng m ca ngi s dng.


i s th 3 y IOAllocateMdl (False) ch ra rng y l vng m d liu kho.
i s th 4 (True) ch ra rng trnh qun l b nh nn qun l (trng nom) cc tin
trnh c giao (c phn cng). i s cui cng (Irp) ch ra Irp IDM c th
c attact. Thc cht, IOAllocateMdl thit lp IrpMdlAdress cho a ch ca MDL
mi c thnh lp, chnh l cch m bn tm thy n v cch m trnh qun l vo
ra cui cngcng tm ra n cho d xo.

232/369
Cc cng v cc thanh ghi (Ports and Registers )
Windows XP s dng m hnh my tnh tru tng nh c m t trong hnh 7.4
cung cp mt giao din driver hp nht nh trong kin trc ca CPU. Trong ch ny,
mt CPU c th c b nh ring bit v cc khng gian a ch. truy cp vo b nh
thit b, CPU s giao cng vic cho mt dng b nh khc nh l mt b nh load hay
lu truy cp trc tip n mt a ch o. CPU dch a ch o ra thnh a ch vt l
bng cch thit lp cc bng trang. truy cp vo mt thit b vo ra c s
ho, bng mt cch khc, CPU cu cu ti mt h thng c bit l x86 vi li ch dn
vo v ra.

Hnh 7.4. Truy cp vo cc cng v cc thanh ghi.

Cc thit b phi c ng Bus l cc cch thc c th c th gii m b nh v cc


a ch vo/ra. Trong trng hp bus PCI, mt cu ni chnh (host) v ra ng i
(ni) gia a ch b nh vt l ca CPU v cc i ch vo/ra ti khng gian a ch ci
m c th truy cp trc tip ti cc thit b. Bt c trong khng gian cu hnh ca thit b
s quyt nh cu ni ny c v c ng i (ni t) t cc thanh ghi ca thit b ti
b nh hoc a ch vo/ra trn CPU thong qua c hai khng gian a ch.

Rng hn khi bn di chuyn c iu kin mt lot code c bin dch trong trnh iu
khin ca bn cho tt c cc th hin c th, cc nh thit k Windows Nt sng to

233/369
ra mt lp cc phn cng tru tng (Hal), ci m ti m ch mt vi ln trong cun
sch ny. Hal cung cp cc hm ci m bn s dng truy xut ti cc ti nguyn b
nh v cc cng.

Hy nhn bng 7.3. Vi bng tm lc ny, bn c th c/ghi hoc l UCHAR/


USHORT/ULONG hoc l mt mng cc kiu ny n hay t (n v i) mt
Cng//Thanh ghi. iu ny to nn 24 hm hal tt c m bn s dng truy cp cc
thit b. T trnh iu khin WDM khng trc tip da vo Hal cho tt c mi th, bn
c th ngh v 24 hm ny tt nh l vic cng khai ton b, nguyn vn hal.

Bng 7.3. Cc hm Hal cho vic truy cp cc cng v cc thanh ghi b nh.

Table 7-3.
HAL
Functions
for
Accessing
Ports and
Memory
Registers
Access
Functions for Port Access Functions for Memory Access
Width
READ_PORT_UCHAR READ_REGISTER_UCHAR
8 bits
WRITE_PORT_UCHAR WRITE_REGISTER_UCHAR
READ_PORT_USHORT READ_REGISTER_USHORT
16 bits
WRITE_PORT_USHORT WRITE_REGISTER_USHORT
READ_PORT_ULONG READ_REGISTER_ULONG
32 bits
WRITE_PORT_ULONG WRITE_REGISTER_ULONG
String of READ_PORT_BUFFER_UCHAR READ_REGISTER_BUFFER_UCHAR
8-bit bytes WRITE_PORT_BUFFER_UCHAR WRITE_REGISTER_BUFFER_UCHAR
String of READ_PORT_BUFFER_USHORT READ_REGISTER_BUFFER_USHORT
16-bit words WRITE_PORT_BUFFER_USHORT WRITE_REGISTER_BUFFER_USHORT
String of
READ_PORT_BUFFER_ULONG READ_REGISTER_BUFFER_ULONG
32-bit -
WRITE_PORT_BUFFER_ULONG WRITE_REGISTER_BUFFER_ULONG
doublewords

Nhng g din ra bn trong ca cc hm truy cp ny l phc thuc vo h


nn(Platform). V d, phin bn Intel x86 ca READ_PORT_CHAR thc hin mt cu
trc IN c mt byte t cng vo /ra c ch nh. Bn b sung Microsoft

234/369
Windows 98/ME tin xa hn .. lu tr trn li gi ca trnh iu khin vi mt li
gi IN hin ti trong mt s trng hp. The Alpha version of this routine performs
a memory fetch. Phin bn intel x86 ca Read_Register_uchar cng thc hin mt l
trnh b nh. . Theo cch khc, phin bn nh vng m ca hm ny (Read-regist-
unchar) thc hin thm mt s cng vic trong mi trng x86 chc chn rngtt c
cc b nh cache c xo (lm sch) mt cch hp l khi m hot ng ny kt thc.

Ti nguyn cng (Port)

Cc thit b vo ra c m hnh ho (IO-Mapped) phi by ra cc thanh ghi phn cng


ci m trn mt s kin trc CPU (bao gm c Intel x86) c nh a ch thong qua
phn mm s dng mt khng gian a ch vo ra c bit. Trn mt s kin trc CPU
khc, khng tn ti khng gian a ch ring bit, v cc thanh ghi ny c nh a
ch thong qua vic s dng mt b nh chnh thc khc. May mn thay, bn khng cn
phi hiu r v s phc tp ca cc a ch ny. Nu bn yu cu thit b mt cng ti
nguyn, mt vng lp ca bn lp qua cc k hiu ti nguyn c dch s tm kim mt
k hiu CmResourceTypePort, v bn s lu thng tin 3 ni.

typedef struct _DEVICE_EXTENSION {

PUCHAR portbase;

ULONG nports;

BOOLEAN mappedport;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

PHYSICAL_ADDRESS portbase; // base address of range

for (ULONG i = 0; i < nres; ++i, ++resource)

switch (resource->Type)

235/369
{

case CmResourceTypePort:

portbase = resource->u.Port.Start;

pdx->nports = resource->u.Port.Length;

pdx->mappedport =

(resource->Flags & CM_RESOURCE_PORT_IO) == 0;

break;

if (pdx->mappedport)

pdx->portbase = (PUCHAR) MmMapIoSpace(portbase,

pdx->nports, MmNonCached);

if (!pdx->portbase)

return STATUS_NO_MEMORY;

else

236/369
pdx->portbase = (PUCHAR) portbase.QuadPart;

1. K hiu ngun cha ng mt tp hp c t tn l u ci m c cc cu trc


h tng cho mi kiu trong s cc kiu ngun chun. u.Port c cc thong tin v
mt ti nguyn cng. u.Port.Start l a ch bt u ca mt vng lin tip cc
cng vo ra, v u.Port.Length l s lng cc cng trong vng (phm vi) .
a ch bt u l mt gi tr a ch vt l 64 bit.
2. Thnh phn Flags ca k hiu ngun cho mt cng ti nguyn c c CM-
RESOURCE-PORT-TO c thit lp nu nh kin trc ca CPU c khng
gian a ch vo ra ring bt cha cc a ch cng thuc v n.
3. Nu c CM_resource_Port_IO b xo, khi m n l mt h nn ca Alpha hoc
mt hang khc nh RISC, bn cn phi gi MnMapIoSpace t c nhn
ca n ch a ch o bng cng c th c truy cp. Vic truy cp ny s
giao cho mt b nh khc, nhng bn vn gi cng . ca cc cng vic
thng nht ca Hal (read_Port_unchar v c th) t trnh iu khin.
4. Nu c CM_RESOURCE_PORT_IO c thit lp, l trong h nn x86, th
bn khng cn v s (nh s ) a ch cng. Bn s gi PORT flavor of
HAL routines t trnh iu khin ca bn khi bn mun truy xut vo mt cng
trong s cc cng ca bn. Cc cng vic thng nht ca HAL (Hal routimes)
i hi mt i s a ch cng Puchar, l l do ti sao chng ta loi c
cc i ch c s vi kiu ny. Theo cch ny th mt phn khc QuadPart dn
n (to ra) con tr 32 bit hoc 64 bt, thch hp vi h nn cho ci m bn
ang bin dch.

- Nh StoptDevice ca bn s gii phng c ti nguyn thc hin nu bn phi tin


hnh s ho cc ti nguyn cng ca bn.

VOID StopDevice(...)

if (pdx->portbase && pdx->mappedport)

MmUnmapIoSpace(pdx->portbase, pdx->nports);

pdx->portbase = NULL;

237/369
}

Ti nguyn b nh (Memory Resources):

Cc thit b m b nh c m hnh ho ch ra cc thanh ghi, ci m phn mm truy


cp s dng cu lnh np v lu tr. Gi tr ti nguyn c dch ny bn ly t trnh
qun l PnP l mt a ch vt l, v bn cn phi d phng cc a ch o c th cha
(bao bc) b nh vt l. Sau , bn s phi gi cc th tc ca Hal, nhng ci m s
lien kt vi cc thanh ghi b nh nh l Read_Register_Unchar , write_register_unchar,
v hn th na. Phn code cu hnh cng nh ch thch ca bn s tng t nh nhng
g c trnh by di y.

typedef struct _DEVICE_EXTENSION {

PUCHAR membase;

ULONG nbytes;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

PHYSICAL_ADDRESS membase; // base address of range

for (ULONG i = 0; i < nres; ++i, ++resource)

switch (resource->Type)

case CmResourceTypeMemory:

membase = resource->u.Memory.Start;

238/369
pdx->nbytes = resource->u.Memory.Length;

break;

pdx->membase = (PUCHAR) MmMapIoSpace(membase, pdx->nbytes,

MmNonCached);

if (!pdx->membase)

return STATUS_NO_MEMORY;

1. Trong sut phn ngun trn (code), u.memory c cc thong tin vti nguyn
b nh. U.memory.Start l a ch bt u ca mt khong (phm vi) lin tip
cc vng ca b nh, v u.memory.length l s byte ca c phm vi . a ch
bt u l mt gi tr a ch vt l 64 bits. Khng phi ngu nhin m u.port v
u.memory l gng nhau- l mt vic lm c mc ch v b c th kim tra
li thy iu ny ng nu bn mun
2. Bn phi gog hm MnMapopace t c nhn ch a ch o thong
qua phm vi b nh c th c truy xut.

Hm StopDevice ca bn vch ra v iu kin cc ti nguyn b nh ca bn

VOID StopDevice(...)

if (pdx->membase)

MmUnmapIoSpace(pdx->membase, pdx->nbytes);

pdx->membase = NULL;

239/369
}

240/369
Phc v ngt (Servicing an Interrupt )
Cu hnh mt ngt (Configuring an Interrupt )

Bn cu hnh mt ngt ngun trong hm StartDevice bng cch gi hm


IoconnectInterrupt s dng cc i s nhng ci m bn c th trch ra n gin t k
hiu ca CmResourceTypeInterrupt. Trnh iu khin v thit b ca bn cm phi hon
ton sn sng lm vic mt cch thch hp khi bn gi hm IoConnectInterrupt, bn
thm ch c khi phi phc v cc ngt ny trc khi m hm ny tr ra gi tr- do vy
bn thng to ra mt li gi gn cui ca tin trnh cu hnh. Mt s thit b c c
im phn cng cho php bn ngn cn chng t ngt. Nu thit b ca bn c cc c
tnh ny, n cc ngt trc khi gi IoConnectInterrupt v cho php cc ngt sau . Cc
cu ch thch v cu lnh cu hnh cho mt ngt tng t nh on code sau:

typedef struct _DEVICE_EXTENSION {

PKINTERRUPT InterruptObject;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

ULONG vector; // interrupt vector

KIRQL irql; // interrupt level

KINTERRUPT_MODE mode; // latching mode

KAFFINITY affinity; // processor affinity

BOOLEAN irqshare; // shared interrupt?

for (ULONG i = 0; i < nres; ++i, ++resource)

241/369
switch (resource->Type)

case CmResourceTypeInterrupt:

irql = (KIRQL) resource->u.Interrupt.Level;

vector = resource->u.Interrupt.Vector;

affinity = resource->u.Interrupt.Affinity;

mode = (resource->Flags == CM_RESOURCE_INTERRUPT_LATCHED)

? Latched : LevelSensitive;

irqshare =

resource->ShareDisposition == CmResourceShareShared;

break;

status = IoConnectInterrupt(&pdx->InterruptObject,

(PKSERVICE_ROUTINE) OnInterrupt, (PVOID) pdx, NULL,

242/369
vector, irql, irql, mode, irqshare, affinity, FALSE);

1. Tham s Level ch ra rng mc yu cu ngt cho ngt ny (IRQL)


2. Tham s Vector ch ta rng ngt cng iu khin cho ngt ny. Chng ta khng
n y l s my v chng ta thc hin hnh ng ny nh l ng ng
ni gia trnh qun l PnP v IoConnectInterrupt. Tt c cc vn ny l
cho HAL hiu c s c ngha g.
3. Affinity l mt bit mt n ci m biu th cho bit nhng CPU no s c
php iu khin ngt ny.
4. Chng ta cn phi ni v IoConnectInterrupt mi khi ngt ca chng ta l edge-
triggered hay l mt level-triggered. Nu trng c ca ngun ny l Cm-
resource-interrupt-latched th chng ta c mt ngt edge-triggered. Cn khng
th chng ta s c mt ngt level_triggered.
5. S dng cu lnh ny c th nhn ra khi no th ngt c chia s.

Trong li gi ti hm IoConnectInterrupt cui ca on code ny, chng ta s n


gin l nhc li cc gi tr chng ta ly ra khi k hiu ngun ca ngt. Tham s u
tin (&pxdinterruptObject) ch tn ra ni lu tr kt qu ca hnh ng kt ni, mt
con tr ti nhn ca i tng ngt l ci m c m t trong ngt ca bn. Tham s
th hai (OnInterrupt) l tn ca dch v ngt ca bn. Ti s tho lun ISR mt bt k hn
trong mt chng. Tham s th 3 (pdx) l gi tr ngu cnh ci m s c vt qua
khi mt tham s ti ISR ti mi mt thi im thit b ca bn ngt. Ti xin ni them v
tham s ng cnh ny sau ti phn Selecting an appropriate Context Argument.

Tham s th 5 v th 6 (vector v irql) theo th t, ch ra s cc vector ngt v mc


ca yu cu ngt, cho cc ngt bn kt ni. Tham s th 8 (mode) l Latched hoc
LevelSensitive biu th ngt l edge-triggered hay l level-triggered. Tham s th
9 l true nu ngt ca bn c chia s vi thit b khc v l False nu ngc li. Tham
s th 10 (affinity) l quan h mt n tin trnh cho ngt ny. Tham s th 11 v cng l
tham s cui cng ch ra h iu hnh c cn phi lu li cc ng cnh Floating-pointer
hay khng khi m thit b ny b ngt. Bi v bn khng uc php thc hin cc tnh
ton Floating-poiter trong ISR trong h nn x86, trnh iu khin c th mang theo s
lun thit lp c ny l False.

Ngt iu khin (Handling Interrupts):

Thit b ca bn c th ngt trn mi CPU nh trc trong mt n tng ng (affinity


mask) m bn ch nh trong li gi ti IoConnectInterrupt. Khi c mt s kin ngt xy
ra, h thng s chuyn ti IRQL ca CPU ti mc ng b ha thch hp v yu cu
kha quay(spin lock) h tr lin hp vi i tng ngt. sau n gi ISR ca bn, ISR
c form nh ngha nh di y:

BOOLEAN OnInterrupt(PKINTERRUPT InterruptObject, PVOID Context)

243/369
{

if (<device not interrupting>)

return FALSE;

<handle interrupt>

return TRUE;

C cu ngt iu khin ca Windows NT l cc ngt cng (Hardware interupts) c th


c chia s bi nhiu thit b. Theo cng vic u tin trong ISR l quyt nh xem
c hay khng thit b ca bn ang ngt thi im hin ti. Nu khng, Bn s tr v
gi tr FASLE ngay tc th v th nhn (kernel) c th gi lnh ngt ti cc driver ca
cc thit b khc. Cn nu c, bn s xa ngt ti mc thit b v tr v gi tr l TRUE.
Liu rng sau nhn c gi n ISR ca cc thit b khc hay khng th n s ph
thuc vo vic liu rng thit b ngt l edge-triggered hay trigger mc( level-triggered)
v trn cc chi tit h nn khc.

Lp trnh gii hn trong ISR (Programming Restrictions in the ISR )ISR thc thi
ti mt IRQL cao hn so vi DISPATCH_LEVEL. Tt c cc on code v d liu s
dng trong mt ISR theo s phi trong b nh nonpaged (nonpaged memory). Hn
na, vic thit lp cc hm ch nhn (kernel-mode functions) m mt ISR c th
gi l rt hn ch.

K t khi mt ISR thc thi ti mt IRQL mc cao, n cho ra cc hot ng khc trn
chnh CPU ca n m yu cu IRQL tng t hoc thp hn. Vi h thng m vic thi
hnh l tt nht th theo , ISR phi thc thi nhanh nht mc c th. V c bn,
l lm s lng cng vic nh nht c yu cu phc v phn cng ca bn v tr
v. tr phi c thm cng vic lm (chng hn hon thnh mt IRP), lp lch cho mt
DPC nm gi, x l vic ny.

Nhng ng c vi v trong vic tnh ton s pi vi hng ngn im thp phn trn ISR
ca bn, ( tr phi thit b ca bn yu cu bn phi lm mt iu g th tht tc ci
v n chc hn l khng th). Mt kh nng phn on tt s ni cho bn bit iu g l
ng n khi bn la chn lm vic gia mt th tc ISR v mt DPC.

BOOLEAN OnInterrupt(PKINTERRUPT InterruptObject,

PDEVICE_EXTENSION pdx)

244/369
UCHAR devstatus = READ_PORT_UCHAR(pdx->portbase);

if ((devstatus & 1))

return FALSE;

<etc.>

Li triu gi th tc tr hon (Deferred Procedure calls):

Vic phc v y mt ngt thit b thng yu cu bn phi thc thi cc thao tc


khng ng lut trong mt ISR hoc l qu t c th tin hnh ti mt IRQL cao
ca mt ISR. c th trnh c nhng vn ny, nhng nh pht trin Windows
NT cung cp c ch li gi th tc tr hon. DPC l mt c ch a mc ch, nhng
thng thung nht n c s dng trong vic kt ni vi mt nm gi cc ngt. Trong
hu ht cc vin cnh ph bin, thit b ISR ca bn m yu cu hin hnh c han
thnh v yu cu mt DPC. Hn th li triu gi n nhn trong DPC thng l ca bn
ti DISPATCH_LEVEL. Du cho vic bhn ch trn cc th tc thit b bn vn c th
triu gi. C t s gii hn nh th by gi bn ang chy mt IRQL thp hn bn
trong ISR. Trong trng hp c bit, vic triu gi cc th tc l hp l chng hn nh
IoCompleteRequest v StartNextPacket chng cn thit v mt logic ti thao tc cui
ca mt I/O

Mi i tng thit b u c mt i tng DPC min ph. iu c ngha l


DEVICE_OBJECT c mt i tng DPC nh r, Dpc c xy dng sn. Bn cn
phi thit lp mt cch vn tt i tng DPC xy dng sn ny sau khi bn to i
tng thit b ca mnh

NTSTATUS AddDevice(...)

PDEVICE_OBJECT fdo;

IoCreateDevice(..., &fdo);

IoInitializeDpcRequest(fdo, DpcForIsr);

245/369
}

IoInitializeDpcRequest l mt Macro trong WDM.H n khi to i tng xy dng sn


DPC (built-in DPC) ca i tng thit b. i s th 2 l mt a ch ca DPC thng
l m ti s ch ra cho cc bn ngay by.

Vi vic khi to cho i tng DPC ti y, ISR c th yu cu mt DPC bng vic s


dng Macro di y:

BOOLEAN OnInterrupt(...)

IoRequestDpc(pdx->DeviceObject, NULL, (PVOID) pdx);

Li gi ny ti cc IoRequestDpc t i tng DPC ca i tng thit b trong mt


hng i ca h thng ln, nh hnh minh ha di y:.

246/369
Hnh 7-5. Tin trnh ca DPC requests.

Gi tr NULL cc thng s pdx l cc gi tr ng cnh (context). Khi khng c hot


ng khc ang xy ra ti DISPATCH_LEVEL, nhn s g b i tng DPC ca bn
t hng i v triu gi ti DPC thng l, c kiu nguyn mu nh sau

VOID DpcForIsr(PKDPC Dpc, PDEVICE_OBJECT fdo, PIRP junk,

PDEVICE_EXTENSION pdx)

Nhng g bn lm bn trong mt DPC thng l s ph thuc vo mnh, ln trn


thit b m bn lm vic. Mt nhim v thch hp s c hon thnh IRP hin ti v
gii phng IRP tip theo t hng i. Nu bn s dng mt trong s cc i tng
DEVQUEUE cho vic i IRP, on m s l nh sau:

VOID DpcForIsr(...)

PIRP Irp = GetCurrentIrp(&pdx->dqRead);

StartNextPacket(&pdx->dqRead, fdo);

IoCompleteRequest(Irp, <boost value>);

Trong on code ny, chng ti da vo s kin m gi DEVQUEUE ghi nh IRP n


gi ti StartIo thng l. IRP chng ta mun hon thnh l mt IRP hin hnh khi chng
ta bt u mt DPC thng l. Theo thi quen chng ta s gi StartNextPacket trc so
vi IoCompleteRequest v th chng ta c th s c thit b bn vi mt yu cu mi
trc khi chng ta bt u vi mt tin trnh di tim nng ca vic hon thnh IRP hin
hnh.

Vic lp lch DPC

n tn lc ny chng ta che y hai chi tit kh quan trng v mt im nh v


DPC. iu chi tit quan trng u tin l n trong s kin m bn c mt i tng DPC
m n b y vo trong mt hng i bi IoRequestDpc. Nu thit b ca bn sinh ra
thm mt ngt ph trc khi DPC thng l thc t mi chy, v nu nh ISR yu cu

247/369
mt DPC khc, nhn n gin s b qua yu cu th hai. Ni cch khc, i tng DPC
ca bn s trong hng i mt ln, khng c vn g c bao nhiu DPC c yu
cu k tip nhau ca ISR ca bn, v nhn s callback ch mt ln. Trong sut mt vic
khn cu ny, th DPC thng l ca bn cn phi hon thnh tt c cc cng vic lin
quan n cc ngt m xy ra DPC cui cng..

n gin nht, bn c th chc chn thit b ca bn s khng b ngt trong thi im


m bn yu cu DPC v thi im m DPC thng lca bn kt thc s lm vic ca
n.

i tng DPC ty bin (Custom DPC Objects )

Bn c th to ra cc i tng DPC khc bn cnh mt DPC vi tn Dpc trong mt i


tng thit b n gin hn ch b nh- trong phn m rng thit b ca bn hoc
mt vi ni khc m khng c nh s (isnt paged)vi mt i tngj KDPC, v
khi to n:

typedef struct _DEVICE_EXTENSION {

KDPC CustomDpc;

};

KeInitializeDpc(&pdx->CustomDpc,

(PKDEFERRED_ROUTINE) DpcRoutine, fdo);

Trong li gi ti KeInitializeDpc, i s th hai l a ch ca DPC thng l trong b


nh nonpaged, v i s th 3 l mt thng s ng cnh ty m s c gi ti DPC
thng l nh i s th 2 ca n..

yu cu mt li gi tr hon (deferred call ) ti mt DPC thng l ty bin, gi


KeInsertQueueDpc:

BOOLEAN inserted = KeInsertQueueDpc(&pdx->CustomDpc, arg1, arg2);

i s arg1 v arg2 l cc con tr ng cnh ty m s c chuyn ti DPC thng l


ty bin .Gi tr tr v l FALSE nu i tng DPC trong mt b x l i ri v
bng TRUE trong trng hp ngc li.

248/369
Ngoi ra, bn c th g b mt i tng DPC t mt hng i x l bng vic triu gi
KeRemoveQueueDpc.

Chng ta c mt on code ch nh thit b nh sau:

NTSTATUS StartDevice(...)

ResetDevice(pdx);

status = IoConnectInterrupt(...);

KeSynchronizeExecution(pdx->InterruptObject,

(PKSYNCHRONIZE_ROUTINE) SetupDevice, pdx);

return STATUS_SUCCESS;

iu ny c ngha l , chng ta vin dn mt th tc tr gip (ResetDevice) thit lp


li phn cng. Mt trong s nhng nhim v ResetDevice l trnh cho thit b khi
s sinh ra bt k ngt no trong mc c th. Sau chng ta gi IoConnectInterrupt
kt ni thit b ngt ti ISR ca mnh. Thm ch trc c khi IoConnectInterrupt tr li,
iu ny l c th cho cc thit b ca chng ta sn sinh ra mt ngt, v th bt k mi
th v trnh iu khin ca chng ta v phn cng phi sn sng i trc. Sau khi kt
ni ngt, chng ta vin dn th tc tr gip khc c tn l SetupDevice lp trnh cho
thit b lm vic theo cch m chng ta mun. chng ta phi ng b bc ny vi ISR
ca mnh bi v n s dng cng thanh ghi phn cng m ISR ca chng ta s s dng.
v chng ta khng mun mi kh nng ca vic gi cc lnh mu thun thit b. Li gi
SetupDevice l bc cui cng trong StartDevice ca PCI42 bi v tri li vi nhng g
ti ni vi cc bn trong chng 2 - PCI42 khng c ng k mi giao din thit
b v theo s khng th c kh nng thi im ny. t.

ResetDevice l mt ch nh thit b cao v c c nh sau:

VOID ResetDevice(PDEVICE_EXTENSION pdx)

249/369
PAGED_CODE();

WRITE_PORT_ULONG((PULONG) (pdx->portbase + MCSR), MCSR_RESET);

LARGE_INTEGER timeout;

timeout.QuadPart = -10 * 10000; // i.e., 10 milliseconds

KeDelayExecutionThread(KernelMode, FALSE, &timeout);

WRITE_PORT_ULONG((PULONG) (pdx->portbase + MCSR), 0);

WRITE_PORT_ULONG((PULONG) (pdx->portbase + INTCSR),

INTCSR_INTERRUPT_MASK);

1. S5933 c mt iu khin ch master control/ thanh ghi trng thi status


register(MCSR) m cc iu khin bus-mastering DMA chuyn, di chuyn v
cc hnh ng khc. Xc nhn 4 trong s cc bit ny s t li cc c trng
khc nhau ca thit b. Ti nh ngha hng s MCSR_RESET l mt mt
n mask bao gm c 4 trong s cc c thit lp li ny (all four of these reset
flags). hng s ny v cc hng s hin nhin cho cc c trng ca S5933 l
file S5933.H file m l b phn ca n PCI42
2. Ba trong s cc c thuc v cc c trng bn trong ca S5933 v s c nh
hng ngay lp tc. Vic thit lp c th 4 xc nhn tn hiu cho thit b
thm mi. xc nhn li vic thit lp thm vo add-on reset, bn phi dt
khot thit lp c ny v 0 Nhn chung, bn mun a phn cng mt bit nh
ca thi im ghi nhn mt xung thit lp li (In general, you want to give
the hardware a little bit of time to recognize a reset pulse.)
KeDelayExecutionThread, m ta tho lun trong chng 4, t lung ny
trong trng thi sleep khong 10 mili giy. Bn c th tng hoc gim hng s
ny nu nh phn cng c cc yu cu khc nhau, nhng ng qun rng thi
gian khng c tnh time -outs khng bao gi nh hn so vi ng h h
thng. T y chng ta ang hn ch lung ca mnh, chng ta cn thit phi
chy ti PASSIVE_LEVEL trong mt ng cnh lung khng ty

250/369
nonarbitrary thread context. Cc iu kin c gp bi v b gi cui
cng l PnP Manager, m gi cho chng ta mt IRP_MN_START_DEVICE
trong s mong i y rng chng ta ang hn ch lung h thng
3. Bc cui cng trong vic thit lp thit bi l xa cc ngt cn treo pending
interupts.. S5933 c 6 c ngt trong mt iu khin ngt/i tng trng thi
(interrupt control/status register) (INTCSR). Vic vit mt 1 bits trong 6 v tr
ny s xa tt c cc ngt treo. (Nu chng ta vit li mt gi tr mt n m c
mt bit 0 trong cc v tr c ngt, trng thi ca ngt khng nh hng. Kiu
bit c ny c gi l read/write-clear hoc n gin l R/WC.) Cc bit khc
trong INTCSR cho php cc ngt ca cc kiu khc nhau. Bng vic vit 0 bit
(bit 0 ?) 0 bitstrong cc im ny, chng ta ang lm mt i kh nng thit b
t ti qui m ln nht c th.

Hm SetupDevice l kh n gin :

VOID SetupDevice(PDEVICE_EXTENSION pdx)

WRITE_PORT_ULONG((PULONG) (pdx->portbase + INTCSR),

INTCSR_IMBI_ENABLE

(INTCSR_MB1 << INTCSR_IMBI_REG_SELECT_SHIFT)

(INTCSR_BYTE0 << INTCSR_IMBI_BYTE_SELECT_SHIFT)

);

Hm ny lp trnh li INTCSR ch nh iu chng ta mun mt ngt c xy ra khi


c s thay i ti byte 0 ca thanh ghi hp th v 1. chng ta c th ch nh cc iu
kin ngt khc cho chip ny, bao gm s trng rng ca mt byte ring bit ca mt
thanh ghi hp th n c ch nh, vic hon thnh mt tin trnh chuyn DMA c,
v vic hon thnh ca mt tin trnh chuyn DMA ghi

Bt u mt thao tc c -Starting a Read Operation

PCI42s StartIo routine cho php m hnh m chng ta c hc ri.

VOID StartIo(IN PDEVICE_OBJECT fdo, IN PIRP Irp)

251/369
PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

if (!stack->Parameters.Read.Length)

StartNextPacket(&pdx->dqReadWrite, fdo);

CompleteRequest(Irp, STATUS_SUCCESS, 0);

return;

pdx->buffer = (PUCHAR) Irp->AssociatedIrp.SystemBuffer;

pdx->nbytes = stack->Parameters.Read.Length;

pdx->numxfer = 0;

KeSynchronizeExecution(pdx->InterruptObject,

(PKSYNCHRONIZE_ROUTINE) TransferFirst, pdx);

1. y chng ta ghi li cc thng s trong phn m rng thit b m t tin


trnh vo ca mt thao tc u vo. Chng ta bo m PCI42 s dng phng thc
DO_BUFFERED_IO, l khng in hnh nhng n gip chng ta to ra trnh iu khin
n gin c s dng nh mt v d.

2. Bi v ngt ca chng ta c kt ni, thit b ca chng ta c th ngt bt k lc


no. ISR s mun truyn cc bytes d liu khi cc ngt xy ra, nhng chng ta mun
c m bo rng ISR khng bao gi b ln xn, rc ri v b m d liu s dng
hoc v s cc bytes chng ta ang c gng c. kim ch tnh hm ca ISR, chng
ta t mt c trong phn m rng thit b nh bn rn m thng thng l FALSE.

252/369
By gi l lc thit lp c v gi tr TRUE. Ging nh thng thng khi chng ta gii
quyt vi mt ti nguyn chia s , chng ta cn phi ng b vic thit lp c vi on
m trong ISR m kim tra n, v theo cn phi vin dn mt th tc SynchCritSection
ging nh ti tho lun t trc. Ngai ra, c th xy ra mt byte d liu c sn
ri. trong trng hp th ngt u tin s khng bao gi xy ra . TransferFirst l mt
th tc tr gip m kim tra vic c v nhng kt qu c th xy ra cho byte u tin
ny. Hm thm vo add-on function c nhiu cch nhn bit vic xa sch hp
mail (hp mail rng), v th n c th on chng gi byte tip theo vo thi im
thch hp.

. y l TransferFirst:

1. VOID TransferFirst(PDEVICE_EXTENSION pdx)


2. {
3. pdx->busy = TRUE;
4. ULONG mbef = READ_PORT_ULONG((PULONG) (pdx-
>portbase + MBEF));
5. if (!(mbef & MBEF_IN1_0))
6. return;
7.
8. *pdx->buffer = READ_PORT_UCHAR(pdx->portbase + IMB1);
9. ++pdx->buffer;
10. ++pdx->numxfer;
11. if (pdx->nbytes == 0)
12. {
13. pdx->busy = FALSE;
14. PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);
15. Irp->IoStatus.Status = STATUS_SUCCESS;
16. Irp->IoStatus.Information = pdx->numxfer;
17. IoRequestDpc(pdx->DeviceObject, NULL, pdx);
18. }

S5933 c mt thanh ghi rng/y cho hp th (empty/full register) (MBEF) cc bit ca


chng ch ra trng thi hin hnh ca mi byte ca mi thanh ghi hp mail. y chng
ta kim tra liu rng byte thanh ghi chng ta s dng cho u (gi tr thanh ghi hp mail
t 1, v 0) hin gi khng c c. Nu nh vy, chng ta s c n, iu ny qu
tht lm rng b m truyn. chng ta c mt th tc con ri (DpcForIsr) th tc
ny bit phi lm g vi mt yu cu y , v th chng ta yu cu mt DPC nu nh
byte u tin tha mn c yu cu. (Gi li rng chng ta ang thc thi ti DIRQL
di s bo v ca mt kha quay ngt bi v chng ta vin dn nh mt th tc
SynchCritSection v th chng ta ko th ch hon thnh IRP ngay by gi )

253/369
S dng ngt (Handling the Interrupt )

Trong thao tc thng thng vi PCI42, cc ngt S5933 khi mt byte d liu mi n
mt hp th 1. ISR sau y s ginh c iu khin:

BOOLEAN OnInterrupt(PKINTERRUPT InterruptObject,

PDEVICE_EXTENSION pdx)

ULONG intcsr =

READ_PORT_ULONG((PULONG) (pdx->portbase + INTCSR));

if (!(intcsr & INTCSR_INTERRUPT_PENDING))

return FALSE;

BOOLEAN dpc = FALSE;

PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);

if (pdx->busy)

if (Irp->Cancel)

status = STATUS_CANCELLED;

else

status = AreRequestsBeingAborted(&pdx->dqReadWrite);

if (!NT_SUCCESS(status))

dpc = TRUE, pdx->nbytes = 0;

254/369
}

while (intcsr & INTCSR_INTERRUPT_PENDING)

if (intcsr & INTCSR_IMBI)

if (pdx->nbytes && pdx->busy)

*pdx->buffer = READ_PORT_UCHAR(pdx->portbase + IMB1);

++pdx->buffer;

++pdx->numxfer;

if (!--pdx->nbytes)

Irp->IoStatus.Information = pdx->numxfer;

dpc = TRUE;

status = STATUS_SUCCESS;

WRITE_PORT_ULONG((PULONG) (pdx->portbase + INTCSR), intcsr);

255/369
intcsr = READ_PORT_ULONG((PULONG) (pdx->portbase + INTCSR));

if (dpc)

pdx->busy = FALSE;

Irp->IoStatus.Status = status;

IoRequestDpc(pdx->DeviceObject, NULL, NULL);

return TRUE;

1. Nhim v u tin ca chng ta l khm ph xem liu rng thit b ring ca


chng ta by gi ang c gng ngt. chng ta c S5933s INTCSR v kim tra
mt bit (INTCSR_INTERRUPT_PENDING) m tm tt tt c cc l do,
nguyn nhn treo ca cc ngt. Nu nh bit ny b xa, chng ta s tr li ngay
lp tc. L do chng ta la chn s dng con tr m rng thit b nh mt i
s ng cnh routineback ny khi ti gi IoConnectInterruptby gi nn b
xa : chng ta cn truy cp ngay lp tc ti cu trc ny c c a ch
cng c s.
2. Khi chng ta s dng mt DEVQUEUE, chng ta da vo, tin tng vo i
tng hng i gi du vt ca IRP hin hnh. Ngt ny c th chng ta
khng mong i bi v thi im hin ti chng ta khng ang phc v
bt k IRp no. Trong trng hp , chng ta vn phi xa ngt nhng khng
nn lm lm bt k iu g khc.
3. Ngoi ra vn c th vi mt s kin Plug and Play hoc s kin ngun xy
ra m s to ra bt k IRP mi no b loi b bi th tc gi thng ip. Hm
AreRequestsBeingAborted ca DEVQUEUEs ni cho chng ta rng chng ta
c th abort (kt thc sm )yu cu hin hnh ngay by gi. Vic kt thc sm

256/369
mt yu cu ang hot ng l mt iu hp l lm vi mt thit b chng
hn nh s thu thp byte tng byte ny (proceeds byte by byte) . Tng t
nh vy, mt tng hay kim tra liu rng IRP c b dng li hay khng
nu nh n chim qu nhiu thi gian kt thc IRP. Nu cc thit b ngt ca
bn ch khi c thc hin vi mt vic truyn ti di, bn c th b i bc
kim tra ny ra khi ISR ca mnh.
4. By gi chng ta bt tay vo mt vng lp m s kt thc khi tt c cc ngt
thit b hin hnh c xa. cui vng lp, chng ta s c li INTCSR
quyt nh xem liu rng bt k cc iu kin ngt no c th pht sinh. Nu
nh vy, chng ta s lp li vng lp . Chng ta khng bn ti thi gian CPU
y- chng ta mun trnh vic cc ngt chy nh thc nc vo h thng
bi v vic phc v mt ngt l tng i t
5. Nu S5933 b ngt bi v mt s kin mailbox , chng ta s c mt byte d
liu mi t mailbox vo trong mt b m I/O cho IRP hin hnh. Nu bn tm
kim mt thanh ghi MBEF ngay sau khi c, bn s thy rng vic c xa bit
tng ng ca thanh ghi mailbox t 1 v 0 (inbound mailbox register 1, byte
0). Ch rng chng ta khng cn thit kim tra MBEF quyt nh xem liu
rng byte ca chng ta thc th c thay i hay khng bi v chng ta lp
trnh cho thit b ch ngt vo lc c mt thay i ti byte n.
6. Vic ghi INTCSR vi ni dung trc ca n c nh hng ti vic xa bit
ngt th 6 R/WC, khng thay i mt vi bit ch c (read-only bits), v bo
ton ci t gc ca tt c cc bit iu khin ch c
7. y chng ta c INTCSR quyt nh xem liu rng cc iu kin ngt
thm vo c xut hin hay khng. nu c chng ta s lp li vng lp
phc v cho chng.
8. Ging nh chng ta tin hnh trn cc on code trc, chng ta thit lp
bin BOOLEANdpc tr thnh TRUE nu mt DPC by gi thch hp hon
thnh IRP hin hnh.

DPC thng l cho PCI42 nh sau::

VOID DpcForIsr(PKDPC Dpc, PDEVICE_OBJECT fdo, PIRP junk,

PDEVICE_EXTENSION pdx)

PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);

StartNextPacket(&pdx->dqReadWrite, fdo);

IoCompleteRequest(Irp, IO_NO_INCREMENT);

257/369
Testing PCI42

Nu nh bn mun kim tra PCI42 trong thao tc, bn cn phi lm mt vi vic. u


tin l tm kim v ci t mt board pht trin S5933DK1 bao gm card giao din
thm vo ISA (ISA add-in interface card). S dng Add Hardware wizard ci t
trnh iu khin S5933DK1.SYS v trnh iu khin PCI42.SYS. ( Ti pht hin rngI
Windows 98 ng nht thit lp board pht trin nh vic s khng chy sound cord v
ti phi g b n i trong Device Manager trc khi t c th tin hnh ci t PCI42
nh trnh iu khin cho n. Nhng Windows XP th lm vic bnh thng)

Sau chy c hai chng trnh ADDONSIM v TEST chng thuc cy th mc PCI42
trong ni dung sch hng dn. ADDONSIM ghi mt gi tr d liu ti mt mailbox
thng qua giao din ISA. TEST c mt byte d liu t PCI42. Vic quyt dnh gi tr
ca byte d liu l bi tp dnh cho cc bn.

258/369
Truy nhp b nh trc tip (Direct Memory Access )
Windows XP h tr vic truy cp trc tip b nh thong qua mt m hnh my tnh tru
tng c m t hnh 7.6. Trong hnh ny, my tnh c coi nh l c mt tp hp
s cc thanh ghi ci m c chuyn i gia a ch vt l ca CPU v a ch bus.
Mi s a ch thanh ghi ny lu gi a ch ca mt trang vt l no . Phn cng
truy cp b nh c hay ghi bng cch ch ra a ch bus hay a ch logic. S cc
thanh ghi ny thc hin cng mt vai tr khi tip nhn bng trang cho phn mm bng
cch cho php phn cng s dng cc gi tr s khc nhau cho cc a ch ca n hn l
cho CPU hiu.

Hnh 7-6. M hnh my tnh tru tng ca b chuyn MDA.

Mt s CUP nh Alpha chng hn th c s thanh ghi phn cng thc t. Mt trong


cc bc khi u cho b chuyn DMA d tr mt s thanh ghi cho qu trnh s dng
ca bn- ti s tho lun vn ny trong phn s chuyn. Mt s loi CPU khc,
nh x86 chng hn th khng c s thanh ghi, bn vit trnh iu khin ca bn tng
t nh h lm. S chuyn thc hin tng bc c th do ngc t di ln ca
cc vng m b nh vt l, ci m ph thuc vo h thng. Trong mt s trng hp
th hot ng ca DMA s c x l s dng vng m o ngc. R rang l mt
s ngi copy d liu n hoc t vng m DMA trc hoc sau khi dch. Trong
trng hp c th, v d nh l khi chng ta lien h mt ng bus ca thit b ch, ci
m l noi t hp ca cc cp- cc giai on ca s chuyn c th khng lm g trong
cu trc m khng c s thanh ghi.

259/369
Nhn ca Windows XP s dng mt cu trc d liu c bit n nh l i tng iu
hp m t cc c tnh DMA ca thit b v iu khin truy cp n cc ngun
c chia s, nh l h thng cc knh DMA v s cc thanh ghi. Bn s ly mt
con tr tr ti i tng iu hp bi li gi IOGetDmAAdapter trong sut qu trnh
StartDevice ca bn. i tng iu hp s c mt con tr tr ti mt cu trc c
gi l DmaOperations ci m khi n bt th cha cc con tr tr ti cc hm m bn
mun gi. Hy xem bng 7.4. Cc hm ny ch ra v tr ch ca hm (v d nh ..) ci
m bn phi s dng phin bn trc ca Windown NT. Thc t, tn ch ny c trong
cc Macro cc m c khai bo trong hm DmaOperations.

Table 7-4. DmaOperations Function Pointers for


DMA Helper Routines
DmaOperations Function Pointer Description
PutDmaAdapter Destroys adapter object
AllocateCommonBuffer Allocates a common buffer
FreeCommonBuffer Releases a common buffer
Reserves adapter and map
AllocateAdapterChannel
registers
Flushes intermediate data buffers
FlushAdapterBuffers
after transfer
Releases adapter object and map
FreeAdapterChannel
registers
FreeMapRegisters Releases map registers only
MapTransfer Programs one stage of a transfer
Gets address alignment required
GetDmaAlignment
for adapter
ReadDmaCounter Determines residual count
Reserves adapter and constructs
GetScatterGatherList
scatter/gather list
PutScatterGatherList Releases scatter/gather list

Chin lc chuyn i (Transfer Strategies):

Cch bn thchin chuyn i DMa ph thuc vo nmt s nhn t sau:

260/369
1. Nu thit b ca bn c Bus-Mastering capability, tt nhin l n cn c in
truy cp vo b nh chnh nu nh bn yu cu n mt s chc nng c bn.
nh l ni bt u, bao nhiu n v d liu c chuyn, bn ang thc hin
vic vo hay ra d liu v nhiu iu khc. Bn s phi hi vi nhng ngi
thit k ra phn cng ca bn lc ra c cc chi tit ny hoc l bn s phi
lm vic vi bng hng dn bit c bn cn phi lm g vi cc mc
phn cng ny.
2. Mt thit b vi kh nng tp hp/tri ra c th chuyn cc khi ln d liu n
hoc i cc vng khng cu hnh ca b nh vt l. S dng scatter/gather l
mt li th ca phn mmbi v n gii hn yu cu v vi cc khi d liu ln
ca cc trang Frame cu hnh. Cc trang ny c th n gin l b kho khi m
chng c tm thy trong b nh vt l v thit b c th b m t bi chng.
3. Nu thit b ca bn khng c Bus ch, bn s s dng h thng iu khin
DMa trn bo mch ch ca my tnh. Kiu ca DMA i khi c gi l
DMA n l (Slave). H thng iu khin DMA lien kt vi cc bus ISA c mt
s gii hn v b nh no n c truy cp v rng ca mt b chuyn n
c th thc hin m khng c chng trnh nh trc. Trnh iu khin ny c
d nh l IESA thiu cc gii hn ny. t nht l trong Windows XP, bn s
khng cn phi bit kiu bus phn cng cu bn cm vo bi v h thng c th
ly ra cc hn ch ny mt cch t ng.
4. Thng thng, h thng DMA bao gm chng trnh s cc thanh ghi phn
cng hoc bn copy d liu trc hay sau ca h thng. nu thit bca bn cn
c hay ghi d liu lien tc, bn khng cn phi thc hin cc bc ny vi
mi yu cu vo.ra, n c th lm chm i qu trnh c chp nhn trong
trng hp c th rt nhiu. V vy bn c th ch nh ci no c bit nh l
vng m chung, ni m cc thit b v cc trnh iu khin ca bn c th
ng thi truy cp ti nhiu thi im.

Tuy nhin trong thc t nhiu chi tit ny s b ph thuc khc nhau vo cch m 4 tc
nhn ny nh hng ln nhau, cc bc m bn thc hin s c nhng c tnh chung.
Hnh 7.7 minh hoc qua t chc ca mt chuyn i. Bn bt u chuyn i t cng
vic StartIo bng cch yu cu quyn s hu ca chnh i tng iu hp.Quyn s
hu ny ch c gi tr khi bn chia s mt knh DMA h thng vi mt thit b khc,
nhng m m hnh DMA ca Windows XP yu cu bn cn phi thc hin cc bc
ny. Khi trnh qun l vo/ra c th cung cp cho bn quyn ny, n s ch nh cho bn
mt s s cc thanh ghi cho qu trnh s dng tm thi cu bnv gi li hnh ng
iu khin b iu hp bn cung cp. TRong hnh ng iu khin b iu hp ca bn,
bn thc hin mt s chuyn i tng bc sp xp phm vi chuyn i u tin
(cng c th l ch c mt). Mt s phm vi c th cn thit nu kh nng s cc
thanh ghi l khng th. Thit b ca bn phi c th cn tr v iu khin nhng iu c
th xy ra gia cc phm vi.

261/369
Figure 7-7. Flow of ownership during DMA.

Mt th tc iu khin b iu hp ca bn c th khi to s cc thanh ghi cho


phm vi u tin, bn bo hiu cho thit b ca mnh bt u hot ng. Thit b ca bn
s thc y mt ngt khi m qu trnh chuyn i ban u c hon tt. V sau th
bn s lit k c mt DPC. Th tc ca DPC s khi u mt phm vi chuyn i
khcnu cn thit hoc nu khng th n s hon thnh yu cu.

i khi theo cch ny, bn s gii phng s cc thanh ghi v i tng iu hp.
S tnh ton thi gian ca hai s kin ny l mt trong s cc chi tit khc ci m phc
thuc vo cc tc nhn ti nu ra u ca phn ny.

Thc hin chuyn i DM (Performing DMA Transfers):

By gi ti s i vo chi tit v nhng ci my c hc ci m vn c gi l mt gi c


s DMA chuyn i, kha cnh no bn chuyn i mt s d liu ring bit bng
cch s dng vng m d liu ci m i cng vi gi yu cu vo/ra. Hy bt u mt
cch n gin v gi s rng bn i din vi mt trng hp rt chung ngy nay: Thit
b ca bn l mt bus PCI master nhng khng c kh nng phn gii/ t tp

Khi bn to ra i tng thit b ca mnh, bt u bn thong thng s biu th


iu bn mun s dng phng thc truy cp trc tip vng m d liu bng
vic thit lp c DO_DIRECT_IO. Bn chn phng thc trc tip bi v bn thm
ch s phi thong qua a ch ca mt k hiu b nh lp danh sch khi mt trong
s cc tham s hm MapTransf bn s gi. S la chn ny s a ra mt s vn
ng quan tm v s sp hang ca vng m. Tr phi m ng dng s dng c
FILE_FLAG_NO_BUFFERING trong li gi ca n ti hm CreatFile, trnh qun l

262/369
vo ra s khng bt buc yu cu xp hang ca i tng thit b trn cc vng m
d liu ch ngi dng (n khng bt buc cc yu cu cho nhn ch li gi
trong ). Nu Hal hoc thit b ca bn yu cu cc vng m DMA bt u trong
mt ranh gii c th, v th bn c th copy t dui ln mt phn nh ca d liu ngi
dng ti hang chnh xc bn trong vng m c c mt hang i yu cu- hoc l
iu hoc nguyn nhn lm sai v yu cu iu c mt vng m khng sp
hng.

TRong hm StartDevice, bn to mt i tng iuhp bng cch s dng on code


nh sau:

DEVICE_DESCRIPTION dd;

RtlZeroMemory(&dd, sizeof(dd));

dd.Version = DEVICE_DESCRIPTION_VERSION;

dd.Master = TRUE;

dd.InterfaceType = InterfaceTypeUndefined;

dd.MaximumLength = MAXTRANSFER;

dd.Dma32BitAddresses = TRUE;

pdx->AdapterObject = IoGetDmaAdapter(pdx->Pdo, &dd,

&pdx->nMapRegisters);

Cu lnh cui cng trong on code ny l quan trng bc nht. IoGetDmaAdapter s


giao tip vi bus iu khin hoc Hal to ra mt i tng iu hp, ci m a ch
ca n c tr v cho bn. Tham s u tin (pdxPdo) nh ngha i tng thit b
vt l cho i tng ca bn. Tham s th hai ch ti cu trc DEVICE_DESCRIPTION
ci m bn khi to m t mt DMA tiu biu cho thit b ca bn. Tham s cui
cng ch ra ni m h thng nn lu gi s lng ln nht cc s ca s cc thanh
ghi m bn s c php c gng lu tr d tr trong sut qu trnh chuyn n. Bn
s cn phi lu rng ti lu tr hai trng trong thit b m rng nhn ly hai d
liu ra t hm ny.

khi u cho hot ng vo/ra, th tc StartIo u tin cn phi d tr mt i


tng bng li gi th tc AllocateAdapterChannel ca i tng. Mt trong cc tham
s truyn ti hm AllocateAdapterChannel l a ch ca mt th tc iu khin iu
hp, ci m trnh qun l vo ra s gi khi s lu tr xong xui. y l on code mu
m bn s dng chun b v thc hin li gi ti AllocateAdapterChannel:

263/369
typedef struct _DEVICE_EXTENSION {

PADAPTER_OBJECT AdapterObject; // device's adapter object

ULONG nMapRegisters; // max # map registers

ULONG nMapRegistersAllocated; // # allocated for this xfer

ULONG numxfer; // # bytes transferred so far

ULONG xfer; // # bytes to transfer during this stage

ULONG nbytes; // # bytes remaining to transfer

PVOID vaddr; // virtual address for current stage

PVOID regbase; // map register base for this stage

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

VOID StartIo(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

PMDL mdl = Irp->MdlAddress;

pdx->numxfer = 0;

pdx->xfer = pdx->nbytes = MmGetMdlByteCount(mdl);

264/369
pdx->vaddr = MmGetMdlVirtualAddress(mdl);

ULONG nregs = ADDRESS_AND_SIZE_TO_SPAN_PAGES(pdx->vaddr,

pdx->nbytes);

if (nregs > pdx->nMapRegisters)

nregs = pdx->nMapRegisters;

pdx->xfer = nregs * PAGE_SIZE - MmGetMdlByteOffset(mdl);

pdx->nMapRegistersAllocated = nregs;

NTSTATUS status = (*pdx->AdapterObject->DmaOperations

->AllocateAdapterChannel)(pdx->AdapterObject, fdo, nregs,

(PDRIVER_CONTROL) AdapterControl, pdx);

if (!NT_SUCCESS(status))

CompleteRequest(Irp, status, 0);

StartNextPacket(&pdx->dqReadWrite, fdo);

1. thit b m rng ca bn cn phi lu tr mt s trng c lien quan n cc


chuyn i DMA. Phn ch thch ch ra cc trng hp cho cc trng ny.
2. y l mt s cu lnh khi to cho cc trng trong thit b m rng cho
phm vi u tin ca s chuyn i.

265/369
3. y chng ta tnh ton s lng cc s cc thanh ghi chng ta yu cu h
thng lu tr cho chng ta trong sut qu trnh chuyn i ny. Chng ta bt
u bng vic tnh ton s lng c yu cu cho ton b s chuyn i ny.
Macro ADDRESS_AND_SIZE_TO_SPAN_PAGES c th a vo mt bn
k khai vng m c th ko di qua ranh gii ca mt trang. Tuy nhin con s
m chng ta i ngc t di ln vi kh nng c th vt qua s ln nht m
chng ta c cho phpbi li gi thong thng ti hm IoGetDmAAdapter.
TRong trng hp ny chng ta cn thc hin mt chuyn i trong nhiu
phm vi. Do vy chng ta o ngc tl ca trang u tin ch s dng con
s chp nhn c ca s cc thanh ghi. Chng ta cng cn phi nh c bao
nhiu s cc thanh ghi m chng ta ang cho php chng ta c th hu
chnh xc con s ny v sau.
4. TRong li gi ti hm AllocateAdapterChannel, chng ta ch ra a ch ca i
tng Adapter, a ch ca i tng thit b ca chng ta, s lng c
tnh ton ca s cc thanh ghi, v a ch ca th tc iu khin iu h ca
chng ta. Tham s cui cng pdx l tham s ng cnh cho th tc iu khin
iu hp ca chng ta.

Thng thng th mt vi thit b c th chia s chung mt i tng iu hp n, i


tng iu hp ang chia s trong cuc sng thc t ch khi bn tin tng vo h thng
iu khin DMA. Cc thit b Bus-Master tn dng cc i tng iu hp thuc quyn
s hu.Nhng bi v bn khng cn phi bit v h thng cc thit b khi bn to ra cc
i tng iu hp, nn bn cng khng cn phi a ra bt c chng minhno vn.
Khi thong thng i tng iu hp ca chng ta s rt bn rn khi bn gi ti
AllocateAdapterChannel, v yu cu ca bn v th c th b t vo trong mt hang i
cho ti khi i tng iuhp tr nn c th x l (rnh ri). Tt c khong tr ny xy
ra bn trong ca AllocateAdapterChannel ci m s gi th tc iu khin iu hp ca
bn khi i tng iu hp v tt c s cc thanh ghi m bn yu cu rng ri.

Nhim v tip theo ca bn l thc hin nhng g m thit b ph thuc ca bn yu cu


ni cho thit b ca bn bit v a ch vt l bt u hot ng trong phn cng
ca bn.

IO_ALLOCATION_ACTION AdapterControl(PDEVICE_OBJECT fdo,

PIRP junk, PVOID regbase, PDEVICE_EXTENSION pdx)

PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);

266/369
PMDL mdl = Irp->MdlAddress;

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

BOOLEAN isread = stack->MajorFunction == IRP_MJ_READ;

pdx->regbase = regbase;

KeFlushIoBuffers(mdl, isread, TRUE);

PHYSICAL_ADDRESS address =

(*pdx->AdapterObject->DmaOperations->MapTransfer)

(pdx->AdapterObject, mdl, regbase, pdx->vaddr, pdx->xfer,

!isread);

return DeallocateObjectKeepRegisters;

1. Tham s th 2 ci m ti t tn l junk to AdapterControl is whatever(bt c


khi no) was in the CurrentIrp field of the device object khi m bn gi hm
AllocateAdapterChannel. Khi bn s dng DEVQUEUE cho hang i IRP, bn
cn phi yu cu i tng DEVQUEUE ci m l IRP hin ti. Nu bn s
dng hang i cc th tc ca Microsoft IoStartPacker & IoStartNextPacket
qunl hang i ca bn th junk s ng l mt IRP. Trong trng hp ny ti
s gi tn Irp thay th.

267/369
2. C mt s iu khc bit gia on code iu khin hot ng vo v ra s
dng DMA, v th n rt thun tin cho vic iu khin c hai hot ng ny
trong th tc con n. Dng code ny kim tra code cho hm chnh cho Irp
quyt nh khi no th hnh ng c hoc ghe xy ra.
3. Tham s regbase ti hm ny l mt iu khin khng r rngtrong vic ch
nh tp hp ca cc thanh ghi s c lu tr trong sut qu trnh s dng ca
bn. Sau ny bn s cn ti gi tr ny, v th bn cn lu tr n trong thit b
m rng ca mnh.
4. KeFlushIoBuffers chc chn rng ni dung ca ton b cc xl trong cc b
nh Cache cho vng m b nh bn ang s dng c lm sch b nh.
Tham s th 3 (TRUE)ch ra rng bn lm sch b nh Cache chun b cho
hot ng ca DMA. Kiu kin trc ca CPU c th yu cu bc ny, bi v
thong thng th hot ng ca DMA hng trc tip n hoc i t b nh m
khng nht thit phi ko theo cc b nh Cache.
5. Th tc Map Transfer thc hin phn cng ca DMA cho mt phm vi ca
chuyn i v tr v a ch vt l khi m vic chuyn i bt u. Ch rng
bn cung cp a ch ca mt MDL nh l tham s th hai ca hm ny. Bi v
bn cn mt MDL ti im ny, nn thong thng th bn cn phi la chn
phng thc DO_DIRECT_IOkhi ln u tin bn to i tng thit b ca
mnh, v trnh qun l vo ra v th s t ng to mt MDL cho bn. Bn cng
cn thong qua cng vi s thanh ghi a ch c s (regbase). Bn ch ra phn
no ca MDL b dnh lu n phm vi ca hot ng ny bng cch cung cp
mt a ch o (pxdvaddr) v mt bute m (pxdxfer). S chuyn i s
s dng tham s a ch o tnh ton i ch offset ca vng m. T n
c th xc nh cc trang vt l ang cha ng d liu ca bn.
6. l mt im m ti bn lp trnh phn cng ca mnh trong thit b theo
mt cch c bit l c yu cu. V d nh l bn c th s dng mt trong
s cc th tc ca WRITE_Xxx Hal gi a ch vt l v cc gi tr ca byte
m n cc thanh ghi trong card ca bn, v t v sau th bn c th iu
khin thanh ghi nhp nhy bt u chuyn i d liu.
7. Chng ta tr ra mt hng s DeAllocateKeepObjectRegister ch ra rng
chng ta khng s dng i tng iu hp nhng chng ta vn s dng s
cc thanh ghi. Trong m\v d c th (bus ch PCI), y khng bao gi c
s ganh ua vi i tng iu hp ti v tr u tin v kh khn ca n l vn
chng ta gii phng i tng iu hp . Trong mt s trng hp bus
ang lm ch khc (bus-mastering) chng ta c th chia s iu khin DMA
vi cc thit b khc. Vic gii phng i tng iu hp ny cho php cc
thit b khc bt u c thc hin chuyn i bng vic s dng cc phn tp
hp ri nhau ca s thanh ghi t mt khi lin m chng ta vn ang s
dng.

268/369
Mt ngt thng xut hin rt nhanh sau khi m chng ta bt u chuyn i.V th tc
ngt dch v lun lun yu cu mt DPC lin h vi s hon thnh ca phm vi u
tin ca chuyn i. Th tc DPC ca bnc th tng t nh sau:

VOID DpcForIsr(PKDPC Dpc, PDEVICE_OBJECT fdo,

PIRP junk, PDEVICE_EXTENSION pdx)

PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);

PMDL mdl = Irp->MdlAddress;

BOOLEAN isread = IoGetCurrentIrpStackLocation(Irp)

->MajorFunction == IRP_MJ_READ;

(*pdx->AdapterObject->DmaOperations->FlushAdapterBuffers)

(pdx->AdapterObject, mdl, pdx->regbase, pdx->vaddr,

pdx->xfer, !isread);

pdx->nbytes -= pdx->xfer;

pdx->numxfer += pdx->xfer;

NTSTATUS status = STATUS_SUCCESS;

if (pdx->nbytes && NT_SUCCESS(status))

269/369
pdx->vaddr = (PVOID) ((PUCHAR) pdx->vaddr + pdx->xfer);

pdx->xfer = pdx->nbytes;

ULONG nregs = ADDRESS_AND_SIZE_TO_SPAN_PAGES(pdx->vaddr,

pdx->nbytes);

if (nregs > pdx->nMapRegistersAllocated)

nregs = pdx->nMapRegistersAllocated;

pdx->xfer = nregs * PAGE_SIZE;

PHYSICAL_ADDRESS address =

(*pdx->AdapterObject->DmaOperations->MapTransfer)

(pdx->AdapterObject, mdl, pdx->regbase, pdx->vaddr,

pdx->xfer, !isread);

else

ULONG numxfer = pdx->numxfer;

(*pdx->AdapterObject->DmaOperations->FreeMapRegisters)

270/369
(pdx->AdapterObject, pdx->regbase,

pdx->nMapRegistersAllocated);

StartNextPacket(&pdx->dqReadWrite, fdo);

CompleteRequest(Irp, status, numxfer);

1. Khi bn s dng DEVQUEUE cho hng i IRP, bn tin tng vo i tng hng
i s gi ng i ca IRP hin thi.

2. Th tc FlushAdapterBuffer iu khin v tr trong chuyn i c yu cu s


dng cc vng m trung gian c s hu bi h thng. Nu nh bn thc hin mt
hnh ng input m ko di qua ranh gii ca trang th d liu vo nm vng m
trung gian v cn phi c copy vo vng m ch ngi dng.

3. y chng ta cp nht s d v s d liu cn li sau khi m phm vi chuyn i


hon tt.

4. Ti v tr ny, bn xc nh phm vi hin thi ca chuyn i c hon tt thnh


cng hoc c li xy ra. V d nh l bn c th c trng thi ca cng hay l xem
xt k kt qu ca mt hot ng tng t c thc hin bi th tc ngt ca bn.
trong v d ny, ti thit lp thuc tnh variable cho trng thi thnh cng (STATUS-
SUCCESS) vi s mong i rng bn thay i n nu tm ra li y.

5. Nu chuyn i ny khng dng li, bn cn phi lp trnh cho mt phm vi khc.


Bc u tin trong tin trnh ny l tnh ton a ch o ca v tr tip theo ca b m
ch ngi dng. Theo ti th vic tnh ton ny n thun ch l lm vic vi mt
s- thc t chng ta cha c gng truy cp vo b nh bng cch s dng a ch o
ny. Tt nhin, truy cp b nh c th l mt kin ti bi v chng ta ang thc hin
mt lung ng cnh tu bin.

6. Cc cu lnh tip theo hu nh y ht nh vic chng ta thc hin trong phm vi u


tin cho StartIo v AdapterControl. Kt qu cui cng s l mt a ch logic ci m c
th c lp trnh trong thit b ca bn. N c th ph hp hay khng ph hp vi a
ch vt l nh c hiu bi CPU. Mt li khuyn nh l chng ta b min cng ch
s dng s cc s thanh ghi nh l chng ta c php bi th tc iu khin iu

271/369
hp; StartIo lu tr con s ny trong trng nMapRegistersAllocate ca thit b m
rng.

7. Nu nh by gi ton b chuyn i hon tt, chng ta cn gii phng s cc thanh


ghi m chng ta va s dng.

8. Cc cu lnh cn li trong th tc DPC iu khin cc my c hc ny hon tt IRP


ci m a cho chng ta ta v tr u tin.

Cc chuyn i s dng cc danh sch t hp/ta ra

Nu phn cng ca bn c h tr t hp/to ra, th h thng ny c mt thi gian thc


hin chuyn i DMA n v i khi thit b ca bn d dng hn. Kh nng to ra/t
hp cho php thit b thc hin mt chuyn i dnh lu n cc trang ci m khng lin
tc trong b nh vt l.

S dng cu trc Scatter_Gather_List c nh ngha trong WDM.H to danh


sch ny:

typedef struct _SCATTER_GATHER_ELEMENT {

PHYSICAL_ADDRESS Address;

ULONG Length;

ULONG_PTR Reserved;

} SCATTER_GATHER_ELEMENT, *PSCATTER_GATHER_ELEMENT;

typedef struct _SCATTER_GATHER_LIST {

ULONG NumberOfElements;

ULONG_PTR Reserved;

SCATTER_GATHER_ELEMENT Elements[];

} SCATTER_GATHER_LIST, *PSCATTER_GATHER_LIST;

Cui cng ti s gi s rng bn c th n gin ch nh mt kch thc ln nht danh


sch Scatter/Gather trong hm AddDevice ca bn v di chuyn n s dng khi m
bn cn:

pdx->sglist = (PSCATTER_GATHER_LIST)

272/369
ExAllocatePool(NonPagedPool, sizeof(SCATTER_GATHER_LIST) +

MAXSG * sizeof(SCATTER_GATHER_ELEMENT));

Vi cc c s h tng ti v tr ny, th tuch AdapterControl ca bn s trng ging


nh l:

IO_ALLOCATION_ACTION AdapterControl(PDEVICE_OBJECT fdo,

PIRP junk, PVOID regbase, PDEVICE_EXTENSION pdx)

PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);

PMDL mdl = Irp->MdlAddress;

BOOLEAN isread = IoGetCurrentIrpStackLocation(Irp)

->MajorFunction == IRP_MJ_READ;

pdx->regbase = regbase;

KeFlushIoBuffers(mdl, isread, TRUE);

PSCATTER_GATHER_LIST sglist = pdx->sglist;

ULONG xfer = pdx->xfer;

PVOID vaddr = pdx->vaddr;

pdx->xfer = 0;

ULONG isg = 0;

while (xfer && isg < MAXSG)

273/369
ULONG elen = xfer;

sglist->Elements[isg].Address =

(*pdx->AdapterObject->DmaOperations->MapTransfer)

(pdx->AdapterObject, mdl, regbase, pdx->vaddr,

&elen, !isread);

sglist->Elements[isg].Length = elen;

xfer -= elen;

pdx->xfer += elen;

vaddr = (PVOID) ((PUCHAR) vaddr + elen);

++isg;

sglist->NumberOfElements = isg;

return DeallocateObjectKeepRegisters;

1. Hy xem m t ban u ca cch ly mt con tr ti IRP ng trong th tc


iu khin iu hp
2. Trc chng ta tnh ton pdxxfer da vo s lng c cho php ca s
cc thanh ghi. By gi chng ta s c gng c th chuyn i c nhiu

274/369
d liu, nhng s lng cho php ca cc phn t ca Scatter/Gather c th
vt qu gii hn mt vi (trong s )chng ta c th chuyn i trong sut
phm vi ny. Trong sut vng lp di y, xfer s l s lng cc byte ci m
chng ta cha lp s , v chng ta s phi tnh ton li pdxxfer nh chng
ta i ( tin hnh thc hin)
3. y l vng lp m ti ha vi cc bn, ni m chng ta c th gi Map
transfer t cc phn t ca Scatter/Gather. Chng ta s tip tc vng lp
cho ti tn khi chng ta s ho ton b phm vi ca chuyn i ny hoc l
cho n tn khi chng ta ra khi cc phn t ca Scatter/Gather, bt c iu no
xy ra u tin.
4. Khi chng ta gi ti s chuyn i (map transfer) cho mt thit b Scatter/
Gather, n s sa i chiu di tham s ch ra c bao nhiu MDL bt u ti
a ch o c cung cp (vaddr) l lin tip nhau theo quy lut t nhin va
c th v th m c s ho bng mt phn t danh sch Scatter/Gather
n. N cng tr ra a ch vt l ca im bt u ca vng k tip.
5. y chnh l ni m chng ta cp nht cc bin ci m m t phm vi hin thi
ca chuyn i. Khi chng ta ri khi vng lp, xfer s b gim xung bng 0
(hoc l chng ta s chy ra ngoi cc phn t ca Scatter/Gather), pxdxfer
s tng n tng s ca tt c cc phn t chng ta c th s ho c.
Chng ta khng cp nht trng pdxxfer trong thit b mm rng- chng ta
ang lm vic trong th tc DPC. l mt trong nhng chi tit phin h khc.
6. y chnh l ni m chng ta tng ch s phn t ca Scatter/Gather phn
nh thc t l chng ta s dng n tng ln.
7. Ti v tr ny, chng ta c phn t Scatter/Gather isg ci m chng ta nn lp
trnh trong thit b ca mnh trong cc thit b ph thuc theo cch thch ng.
Sau chng ta nn khi ng hot ng ca thit b ny trong yu cu.
8. Tr v DeAllocateObjectKeepRegisters l hp l cho mt thit b bus ang lm
ch. V mt l thuyt bn c th c mt thit b khng lm ch vi kh nng
Scatter/Gather, v n s tr ra KeepObject thay v cc gi tr khc.

Th tc StartIo s c dng nh:

VOID StartIo(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

NTSTATUS status;

275/369
PMDL mdl = Irp->MdlAddress;

ULONG nbytes = MmGetMdlByteCount(mdl);

PVOID vaddr = MmGetMdlVirtualAddress(mdl);

BOOLEAN isread = stack->MajorFunction == IRP_MJ_READ;

pdx->numxfer = 0;

pdx->nbytes = nbytes;

status =

(*pdx->AdapterObject->DmaOperations->GetScatterGatherList)

(pdx->AdapterObject, fdo, mdl, vaddr, nbytes,

(PDRIVER_LIST_CONTROL) DmaExecutionRoutine, pdx, !isread);

if (!NT_SUCCESS(status))

CompleteRequest(Irp, status, 0);

StartNextPacket(&pdx->dqReadWrite, fdo);

Trong StartDevice, bn c mt bt nh ca phn code thm vo ch nh knh DMA


m trnh qun l PnP phn cng cho bn, v bn cng cn khi to nhiu hn cc trng
ca cu trc DEVICE_DESCRIPTION cho IoGetDmAAdapter:

NTSTATUS StartDevice(...)

ULONG dmachannel; // system DMA channel #

ULONG dmaport; // MCA bus port number

276/369
for (ULONG i = 0; i < nres; ++i, ++resource)

switch (resource->Type)

case CmResourceTypeDma:

dmachannel = resource->u.Dma.Channel;

dmaport = resource->u.Dma.Port;

break;

DEVICE_DESCRIPTION dd;

RtlZeroMemory(&dd, sizeof(dd));

dd.Version = DEVICE_DESCRIPTION_VERSION;

dd.InterfaceType = InterfaceTypeUndefined;

dd.MaximumLength = MAXTRANSFER;

dd.DmaChannel = dmachannel;

dd.DmaPort = dmaport;

277/369
dd.DemandMode = ??;

dd.AutoInitialize = ??;

dd.IgnoreCount = ??;

dd.DmaWidth = ??;

dd.DmaSpeed = ??;

pdx->AdapterObject = IoGetDmaAdapter(...);

1. Danh sch cc ngun ti nguyn vo/ra s c mt ti nguyn DMA, tnhng g


m bn cn trch ra knh v cc s hiu cng. S knh nh ngha mt trong
s cc knh c h tr bi mt h thng iu khin DMA. S hiu cng ch l
duy nht trong bus thit b MCA
2. Bt u t y, bn buc phi khi to mt s trng ca cu trc
DEVICE_DESCRIPTION da vo hiu bit ca bn v thit b ca bn. Hy
xem bng 7.5

Tt c mi iu v iu khin iu hp ca bn v cc th tc DPC s ging ht vi


on code m chng ta c xem xt phn u ca phn iu khin thit b bus-
mastering khng c kh nng s cc thanh ghi ngoi tr hai chi tit nh. Th nht l,
adaptercontrol tr ra mt gi tr khc

IO_ALLOCATION_ACTION AdapterControl(...)

return KeepObject;

Gi tr tr ra KeepObject ch ra rng chng ta mun gi li iu khin thng qua s


cc thanh ghi v knh DMA chng ta ang s dng. Th hai l, t khi chng ta khng
gii phng i tng iu hp khi m AdapterControl c tr ra, chng ta phi lm
vic ny trong th tc DPC bi li gi FreeAdapterChannel thay v FreeMapRegister:

VOID DpcForIsr(...)

278/369
{

(*pdx->AdapterObject->DmaOperations->FreeAdapterChannel)

(pdx->AdapterObject);

S dng mt b m chung (Using a Common Buffer).

Bn thng ch nh b m chung ca bn ti thi im StartDevice sau khi to ra i


tng iu hp ca bn:

typedef struct _DEVICE_EXTENSION {

PVOID vaCommonBuffer;

PHYSICAL_ADDRESS paCommonBuffer;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

dd.Dma32BitAddresses = ??;

dd.Dma64BitAddresses = ??;

pdx->AdapterObject = IoGetDmaAdapter(...);

pdx->vaCommonBuffer =

(*pdx->AdapterObject->DmaOperations->AllocateCommonBuffer)

(pdx->AdapterObject, <length>, &pdx->paCommonBuffer, FALSE);

279/369
u tin cho gi IoGetDmAAdapter, bn thit lp cc c Dma32BitAddresses &
Dma64BitAddresses trong cu trc DEVICE_DESCRIPTION ni r v cc kh nng
a ch ca thit b ca bn. iu l: nu thit b ca bn c th nh a ch mt b
m s dng i ch vt l 32 bt, hy thit lp Dma32BitAddresses thnh true. Nu n
c th nh a ch b m s dng a ch 64 bt th hy thit lp Dma64BitAddresses
thnh True.

Trong li gi ti hm AllocateCommonBuffer, tham s th hai l byte di ca b


m bn mun ch nh. i s th 4 l gi tr Boolean ci m ch nh bn mun b
nh c ch nh l c chp nhn trong b nh cache ca CPU (TRUE) hay khng
(FALSE)

AllocateCommonBuffer tr ra mt a ch o. y l mt a ch bn s dng trnh iu


khin ca bn truy cp vo vng m c ch nh. AllocateCommonBuffer cng
thit lp PHYSICAL_ADDRESS c tr ti bi tham s th 3 : l a ch logic c
s dng vi thit b ca bn cho chnh vng m ca n truy cp

Thit b Bus-Master n gin

b phn iu khin mu PKTDMA trong ni dung sch hng dn nh th no thc


hin hot ng bus-master DMA khng cn h tr scatter/gather bng s sng mai mi
chp (matchmaker chip) AMCC S5933 PCI. Bn tho lun chi tit nh th no b
iu khin khi to thit b trong StartDevice v nh th no khi to mt chuyn
giao DMA trong StartIo. Bn cng cn phi tho lun v tt c cc i xy ra trong
AdapterControl trong thit b v th tc DpcForIsr . ti trnh by ngn gn u l
th tc ny cn phi c mt vi dng code thit b - ph thuc cho vic bt u 1 hot
ng ca thit b . Bn c th vit 1 hm helper c tn l StartTransfer vi mc ch:

VOID StartTransfer(PDEVICE_EXTENSION pdx,

PHYSICAL_ADDRESS address, BOOLEAN isread)

ULONG mcsr = READ_PORT_ULONG((PULONG)(pdx->portbase + MCSR);

ULONG intcsr =

READ_PORT_ULONG((PULONG)(pdx->portbase + INTCSR);

if (isread)

280/369
mcsr = MCSR_WRITE_NEED4 MCSR_WRITE_ENABLE;

intcsr = INTCSR_WTCI_ENABLE;

WRITE_PORT_ULONG((PULONG)(pdx->portbase + MWTC), pdx->xfer);

WRITE_PORT_ULONG((PULONG)(pdx->portbase + MWAR),

address.LowPart);

else

mcsr = MCSR_READ_NEED4 MCSR_READ_ENABLE;

intcsr = INTCSR_RTCI_ENABLE;

WRITE_PORT_ULONG((PULONG)(pdx->portbase + MRTC), pdx->xfer);

WRITE_PORT_ULONG((PULONG)(pdx->portbase + MRAR),

address.LowPart);

WRITE_PORT_ULONG((PULONG)(pdx->portbase + INTCSR), intcsr);

WRITE_PORT_ULONG((PULONG)(pdx->portbase + MCSR), mcsr);

281/369
Th tc ci t thanh ghi hot ng S5933 cho chuyn giao DMA v sau chuyn giao
bt u chy . Cc Bc ca qu trnh nh sau :

1. a ch chng trnh ( MxAR ) v tng s chuyn giao (MxTC) thanh ghi thch hp
nh hng cho lung d liu . AMCC c chn cho gii hn c miu t hot
ng truyn d liu ra thit b . Bi vy khi chng ta thc hin y IRP_MJ_WRITE,
chng trnh s c hot ng ti chip level . a ch chng ta sa dng l a ch logic
c quay tr li bi MapTransfer.

2. Cho php mt ngt khi m s chuyn i dn ti 0 bi vic vit Intcsr

1. Bt u s chuyn i bng cch thit lp mt bt cho php chuyn i trong


MCSR.

on code ny khng c r rng cho lm, nhng S5933 l mt kh nng thc t ca


vic mt DMA c v mt DMA vit ti cng mt thi im. Ti vit PKTdma
theo cch ch vi mt hot ng (hoc l c hoc l vit) c th xy ra. khi
qut ho trnh iu khin cho php c hai loi hot ng xy ra ng thi, bn cn
ti phng tin tch cc hng i cho vic c v ghi IRP v to ra hai i tng
thit b v hai i tng iu hp- mt cp c v cp cn li vit. trnh tnh
trng lng tng ca vic c gng i gp i cc i tng ging nhau bn trong
AllocateAdapterChannel. Ti ngh rng vic thm s phc tp vo trong v d mu s
gy kh khn cho bn. (ti bit rng ti cm thy lc quan v k nng m t hm
rng ti khng lm cho bn thy ln ln, nhng n c th s ti t hn)

iu khin cc ngt trong PKTDMA

PCI42 bao gm mt th tc ngt ci m thc hin mt bit nh ca cng vic di


chuyn d liu. Th tc ngt ca PKTDMA th n gin hn.

BOOLEAN OnInterrupt(PKINTERRUPT InterruptObject,

PDEVICE_EXTENSION pdx)

ULONG intcsr =

READ_PORT_ULONG((PULONG) (pdx->portbase + INTCSR));

if (!(intcsr & INTCSR_INTERRUPT_PENDING))

return FALSE;

282/369
ULONG mcsr = READ_PORT_ULONG((PULONG) (pdx->portbase + MCSR));

WRITE_PORT_ULONG((PULONG) (pdx->portbase + MCSR),

mcsr & ~(MCSR_WRITE_ENABLE MCSR_READ_ENABLE));

intcsr &= ~(INTCSR_WTCI_ENABLE INTCSR_RTCI_ENABLE);

BOOLEAN dpc = GetCurrentIrp(&pdx->dqReadWrite) != NULL;

while (intcsr & INTCSR_INTERRUPT_PENDING)

InterlockedOr(&pdx->intcsr, intcsr);

WRITE_PORT_ULONG((PULONG) (pdx->portbase + INTCSR), intcsr);

intcsr = READ_PORT_ULONG((PULONG) (pdx->portbase + INTCSR));

if (dpc)

IoRequestDpc(pdx->DeviceObject, NULL, NULL);

return TRUE;

Ti s ch m t v cch thc m trong ISR khng ging vi trong PCI42:

1. S5933 s duy tr c gng chuyn i d liu- ci m l ch ca thanh ghi


m- lu cho n khi cc bt cho php c thit lp trong MCSR. Cu lnh
ny xo c hai bt. Nu trnh iu khin ca bn ang iu khin ng thi c
vic c v ghi, bn cn ch nh loi hot ng no kt thc bng vic kim
tra cc c ca ngt trong INTCSR v sau bn disable s chuyn i theo
phng din .
2. Chng ta s vit li mt on ngn INTCSR xo ngt. Cu lnh ny m
bo rng chng ta cng s disable vic chuyn i -m cc ngt 0 chng

283/369
khng th sy ra thm ln no na. Mt ln na, trnh iu khin ca bn ci
m iu khin c v ghi ng thi c th khng ch c kh nng ngt ci m
xy ra.

Kim tra PKTDMA

Bn c th kim tra PKTDMA nu nh bn c mt bng mch pht trin S5933DK1.


Nu bn chy chng trnh test PCI42, th bn ci t 5933DK1. SYS driver ISA
thm vo- trn card interface. Nu khng, bn cn phi ci t driver cho chng trnh
test ny. Sau ci t PKTDMA.SYS nh l trnh iu khin cho chnh bo mch pht
trin S5933. Bn c th chy TEST.EXE kim tra chng trnh ci m trong th mc
PKTDMA \TEST\ DEBUG. Test s thc hin ghi cho 8192 bytes cho PKTDMA. N s
pht ra mt DeviceIoCntrol cho S5933DK1 c li d liu t mtt thm vo, v n
s kim tra rng n c c cc gi tr ng khng.

Nhng ch v tnh tng thch ca Windows 98/Me.

MnGetAddressForMdlSafe l mt macro ci m dn chng rng mt hm


(MmMapLockedPagesSpecifyCache) ci m Windows 98/Me khng xut ra. Cc macro
c, MnGetAddressForMdl gi y b phn i. Vic thm tra trnh iu khin (Driver
Verifier) s flag mt li gi thi gian thc thi ti macro c. im khc bit y l:
MnGetAddressForMdl s bug check nu nh y khng c cc s tip nhn bng
trang s ho b nh c ch nh, nhng ngc li MnGetAddressForMdlSafe
s n gin l tr v mt con tr Null

y c th c mt cch gii quyt khc cho vn c a ra bng


MnGetAddressForMdlSafe:

CSHORT oldfail = mdl->MdlFlags & MDL_MAPPING_CAN_FAIL;

mdl->MdlFlags = MDL_MAPPING_CAN_FAIL;

PVOID address = MmMapLockedPages(mdl, KernelMode);

if (!oldfail)

mdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;

Thit lp c MDL_MAPPING_CAN_FAIL nguyn nhn lm cho Windows 200 v XP


ly c ng dn bn trong on code nh l MnMapLockedPagesSpecifyCache,
bng cch y hon thnh c lnh s dng macro mi. Windows 98/ME l i c
ny (v n lun tr v gi tr Null trong cc trng hp sai, v vy y khng bao gi
cn mt c hay mt macro mi.)

284/369
Nu bn ang s dng GENERIC.SYS, li gi n gin
GenericGetSystemAddressForMdl, ci m cha nhng iu ni on code trn. Ti
khng c gng thm vo MnMapLockedPagesSpecifyCache ti WDMSTUB.SYS
(xem phc lc A) bi v Windows 98/ME khng cung cp cc b phn cn thit h
tr hon ton cho hm ny.

285/369
Bi 17: IU KHIN VO/RA V HM
IU KHIN PLUG AND PLAY
Hm DeviceIoControl API (The DeviceIoControl API)
User-mode DeviceIoControl API c nguyn mu sau y:

result = DeviceIoControl(Handle, Code, InputData, InputLength,

OutputData, OutputLength, &Feedback, &Overlapped);

Handle (HANDLE) l mt knh iu khin m i vi thit b. Bn thu c knh ny


bng vic gi l CreateFile trong lnh sau y :

Handle = CreateFile("\\\\.\\IOCTL", GENERIC_READ GENERIC_WRITE,

0, NULL, OPEN_EXISTING, flags, NULL);

if (Handle == INVALID_HANDLE_VALUE)

<error>

CloseHandle(Handle);

Nhng c i s ti CreateFile cng l FILE_FLAG_OVERLAPPED hay 0 ch


ra bn s biu din c hay khng s hot ng d b vi knh iu khin tp tin
ny. Trong khi bn c knh iu khin m, bn c th lm nhng s gi ti ReadFile,
WriteFile, hay DeviceIoControl. Hoc khi no bn truy cp thit b, bn cn phi ng
dt khot knh iu khin bng vic gi l CloseHandle.Phi hng vo trong tm
tr, th nhng, h iu hnh t ng ng bt k knh iu khin no m c
m v pha tri khi qu trnh (ca) cc bn hon thnh. Code (DWORD) i s ti
DeviceIoControl l mt m iu khin m ch bo thao tc iu khin (php ton kim
tra) bn mun thc hin. Ti s bn lun v vic bn nh ngha nhng m ny hi
xa hn nh th no trn (in Defining I/O Control Codes). InputData (PVOID) v
InputLength (DWORD) nhng i sm t mt vng d liu m bn gi ti trnh iu
khin thit b. (Ngha l, d liu ny c nhp vo t phi cnh (ca) trnh iu khin.).
The OutputData (PVOID) and OutputLength (DWORD) nhng i sm t mt vng
d liu m trnh iu khin c th hon ton hay tng phn lm y thng tin m
n mun nhn quay tr li cho bn. (Ngha l, d liu ny l u ra t phi cnh (ca)

286/369
trnh iu khin.) Trnh iu khin s cp nht the Feedback variable (a DWORD)
ch bo bao nhiu nhng byte ca d liu ra n a cho bn mt sau. Hnh 9-1 minh
ha mi quan h ca nhng b m ny vi ng dng v trnh iu khin. Cu trc
Overlapped (OVERLAPPED) c dng gip kim sot mt tc v ng b, m
l ti ca mc tip theo. Nu bn c ch r FILE_FLAG_OVERLAPPED trong s
gi ti CreateFile, bn phi ch r OVERLAPPED con tr cu trc. Nu bn khng ch
r FILE_FLAG_OVERLAPPED, bn c l cung cp tt NULL cho i scui cng
ny bi v h thng s l i n.

Hnh 9-1 . u vo v nhng b m ra cho DeviceIoControl.

Liu c phi mt thao tc iu khin (php ton kim tra) c bit yu cu mt b m


vo hay mt b m ra ph thuc vo chc nng c thc hin.Chng hn, mt iu
khin I/O (IOCTL) m khi phc s phin bn ca trnh iu khin c l ch yu cu
mt b m ra. Mt IOCTL m n thun thng bo trnh iu khin ca thc t no
gn lin vi ng dng c l ch yu cu mt b m vo. Bn c th hnh dung s
hot ng nhng thao tc khc m yu cu c hai hoc khng ci no ca u vo v
nhng b m ra-n mi th ph thuc vo ci m thao tc iu khin (php ton kim
tra) lm.. Gi tr tr li t DeviceIoControl l mt gi tr i s Boole m ch bo thnh
cng ( Nu Tht ) hay s tht bi ( nu Sai). Trong mt hon cnh tht bi, ng dng c
th gi cho GetLastError tm ra ti sao s gi b ph sn.

287/369
Synchronous v Asynchronous gi ti DeviceIoControl

Khi bn lm mt s gi ng b ti DeviceIoControl, nhng khi lung gi cho n


thao tc iu khin (php ton kim tra) hon thnh. Chng hn:

HANDLE Handle = CreateFile("\\\\.\\IOCTL", ..., 0, NULL);

DWORD version, junk;

if (DeviceIoControl(Handle, IOCTL_GET_VERSION_BUFFERED,

NULL, 0, &version, sizeof(version), &junk, NULL))

printf("IOCTL.SYS version %d.%2.2d\n", HIWORD(version),

LOWORD(version));

else

printf("Error %d in IOCTL_GET_VERSION_BUFFERED call\n",

GetLastError());

y chng ti m iu khin thit b khng c c FILE_FLAG_OVERLAPPED.


Vic gi k tip ca chng ta ti DeviceIoControl bi vy khng tr li cho n khi
trnh iu khin cung cp cu tr li m chng ti yu cu.

Khi bn lm mt s gi khng ng b ti DeviceIoControl, lung cuc gi khng


hng ti khi ngay lp tc. Thay vo , n tip tc x l cho n khi n t n im
ni n yu cu kt qu ca thao tc iu khin (php ton kim tra). Ti im n gi
l mt API m s ngn chn lung cho n khi trnh iu khin hon thnh thao tc.
Chng hn:

HANDLE Handle = CreateFile("\\\\.\\IOCTL", ...,

FILE_FLAG_OVERLAPPED, NULL);

DWORD version, junk;

OVERLAPPED Overlapped;

Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

DWORD code;

288/369
if (DeviceIoControl(Handle, ..., &Overlapped))

code = 0;

else

code = GetLastError();

<continue processing>

if (code == ERROR_IO_PENDING)

if (GetOverlappedResult(Handle, &Overlapped, &junk, TRUE))

code = 0;

else

code = GetLastError();

CloseHandle(Overlapped.hEvent);

if (code != 0)

<error>

nh ngha nhng m iu khin vo/ra

i s m ti DeviceIoControl l mt s 32- bit hng s m bn nh ngha s dng b


tin x l CTL_CODE v m iu l b phn ca c hai DDK v nn tng SDK.
Hnh 9-2 minh ha cch trong h iu hnh phn chia ca mt trong 32-bit nhng m
vo trong nhng trng con.

Hnh 9-2. Nhng lnh vc trong mt m iu khin vo/ra .

Nhng lnh vc c s gii thch sau y:

289/369
Kiu thit b (16 bt, i s u tin ti CTL_CODE) ch bo kiu ca thit b m thc
hin thao tc iu khin (php ton kim tra) ny.

_Bn cn phi s dng cng gi tr (Chng hn, FILE_DEVICE_UNKNOWN) bn s


dng trong trnh iu khin khi bn gi IoCreateDevice. (Nhng m kiu thit b h tp
tin gy ra qun l I/O s dng mt m chc nng chnh khc nhau cho IRP)

_M truy nhp (2 bt, i s th t ti CTL_CODE ) ch bo quyn li truy nhp mt


ng dng cn ti thit b ca n pht hnh thao tc iu khin (php ton kim tra)
ny.

_M chc nng (12 bt, i s th hai ti CTL_CODE) ch bo chnh xc thao tc iu


khin (php ton kim tra) no m iu ny vit m m t. Microsoft d tr na u tin
ca phm vi ca cc trng ny-iu , nh gi t 0 n 2047-cho tiu chun kim
sot nhng thao tc. Bn v Ti bi vy gn nhng gi tr trong phm vi t 2048 n
4095. Mc ch chnh ca quy c ny s cho php bn nh ngha nhng thao tc iu
khin (php ton kim tra) ring t cho nhng thit b tiu chun.

_Phng php m (2 bt, i sth ba ti CTL_CODE) ch bo I/O Manager c x


l u vo v nhng b m ra cung cp bi ng dng nh th no. Ti s c mt tho
thun ln ni v lnh vc ny trong mc tip theo, khi Ti m t lm sao thc hin
IRP_MJ_DEVICE_CONTROL trong mt trnh iu khin.

290/369
iu khin IRP MJ DEVICE CONTROL
S nh v cha nhng tham s c lit k trong Bng 9-2. Nhng trnh iu khin
Lc t chng c l gii thch mt s mt m ring tr phi nh-nu chnh xc vit
m, ci -i qua tt c nhng ngi ci khc xung ngn xp. Tht ra, mt chc nng
lin lc m hiu x l IOCTL s c tr u nh th no trong chng trnh iu
khin-a s hp l trong trnh iu khin chc nng.

Table 9-2. Stack Location Parameters for


IRP_MJ_DEVICE_CONTROL
Parameters.DeviceIoControl Field Description
Length of the output buffersixth
OutputBufferLength
argument to DeviceIoControl
Length of the input bufferfourth
InputBufferLength
argument to DeviceIoControl
Control codesecond argument to
IoControlCode
DeviceIoControl
User-mode virtual address of input
Type3InputBuffer
buffer for METHOD_NEITHER

Mt chc nng lin lc thuc v b xng cho nhng thao tc iu khin (php ton
kim tra) ging nh th ny:

#pragma PAGEDCODE

NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp)

1->

PAGED_CODE();

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

NTSTATUS status = STATUS_SUCCESS;

291/369
ULONG info = 0;

2->

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

ULONG cbin =

stack->Parameters.DeviceIoControl.InputBufferLength;

ULONG cbout =

stack->Parameters.DeviceIoControl.OutputBufferLength;

ULONG code =

stack->Parameters.DeviceIoControl.IoControlCode;

switch (code)

3->

default:

status = STATUS_INVALID_DEVICE_REQUEST;

break;

return CompleteRequest(Irp, status, info);

1. Bn c th tin chc c gh thm PASSIVE_LEVEL, nh vy khng c l do


c bit cho mt s lin lc n gin vn hnh l bt c ni u nhng nh s trang
k c.

2. Vi s pht biu tip theo rt m chc nng v nhng kch thc vng m t lin
hip nhng tham s trong chng vo/ra. Bn thng cn nhng gi tr ny khng c vn
IOCTL c bit no m bn x l, v vy Ti lun lun tm thy d dng hn nhng
s pht biu ny trong chc nng

292/369
3. y l ni bn sng to bi tp ca mnh bng vic chn nhng nhn trng hp (cho)
thao tc IOCTL khc nhau h tr bn..

4. y l mt tng tt tr li mt tnh trng vit m liu y ngha nu bn c


a cho mt IOCTL

293/369
Nhng thao tc bn trong iu khin IO (Internal IO
Control Operations)
H thng s dng IRP_MJ_DEVICE_CONTROL thc hin mt s gi
DeviceIoControl t kiu ngi s dng. Nhng trnh iu khin i khi cng cn ni
chuyn vi nhau, v h s dng IRP_MJ_INTERNAL_DEVICE_CONTROL lin quan
lm. Mt chui m tiu biu i theo Nh sau:

ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

KEVENT event;

KeInitializeEvent(&event, NotificationEvent, FALSE);

IO_STATUS_BLOCK iostatus;

PIRP Irp = IoBuildDeviceIoControlRequest(IoControlCode,

DeviceObject, pInBuffer, cbInBuffer, pOutBuffer, cbOutBuffer,

TRUE, &event, &iostatus);

NTSTATUS status = IoCallDriver(DeviceObject, Irp);

if (NT_SUCCESS(status))

KeWaitForSingleObject(&event, Executive, KernelMode,

FALSE, NULL);

The IoControlCode argument to IoBuildDeviceIoControlRequest l mt m iu khin


biu th thao tc bn mun b iu khin thit b ch thc hin. M ny l cng
loi m Bn s dng vi nhng thao tc iu khin bnh thng.DeviceObject l mt
con tr ti DEVICE_OBJECT m c trnh iu khin s thc hin ch bo thao tc.
u vo v nhng tham s b m ra phc v cng mc ch vi nhng bn sao
ca h trong mt s gi DeviceIoControl kiu ngi s dng. i s(th) by, m
Ti ch r nh TRUE trong on ny, ch ra rng bn xy dng mt thao tc iu
khin (php ton kim tra) bn trong. (Bn c th ni FALSE y to ra mt
IRP_MJ_DEVICE_CONTROL thay vo .) Ti s m t mc ch (ca) s kin v
nhng i siostatus trong mt mu.

294/369
IoBuildDeviceIoControlRequest builds an IRP v khi to s nh v (v tr) chng u
tin m t m tc v v nhng b m bn ch r. N tr li con tr IRP cho bn
bn c th lm bt k s khi to b sung no m c l c yu cu. Trong Chng
12, chng hn, Ti s ch ra bn lm sao s dng mt yu cu kim sot ni b gi
mt khi yu cu USB (URB) ti trnh iu khin USB. Mt phn m qu trnh bao
gm t mt lnh vc tham s chng ti im ti URB. Bn gi l IoCallDriver gi
IRP cho thit b ch. Nu gi tr tr li i qua s th NT_SUCCESS, bn i trn i
tng s kin bn ch r nh i s(th) tm Ti IoBuildDeviceIoControlRequest. The
I/O Manager s t s kin khi kt thc IRP, v n s cng in vo cu trc iostatus
(ca) cc bn vi tnh trng cui v thng tin nhng gi tr. Cui cng n s gi l
IoFreeIrp gii phng IRP. Vy th, Bn khng mun truy nhp con tr IRP cht no
sau khi bn gi l IoCallDriver.

S khng phi l mt tng tt khi s dng cng s lin lc thng l (cho) iu khin
bn trong v ngoi, nhn tin, t nht khng phi khng c vic kim tra m chc nng
chnh (ca) IRP. y l mt v d ca ti sao khng: Gi thit trnh iu khin (ca)
cc bn c mt giao din iu khin ngoi m cho php mt ng dng hi giao din
kim sot ni b s lphaanjboj phn iu khin (ca) cc phin bn m cho php mt
ngi gi kiu nhn c th tin cn c xc nh mt b mt sng cn m bn khng
mun chia s vi ngi s dng- nhng

chng trnh kiu. Ri gi thit bn s dng mt th tc x l c hai giao din, nh


trong v d ny:

NTSTATUS DriverEntry(...)

DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =

DispatchControl;

DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =

DispatchControl;

NTSTATUS DispatchControl(...)

switch (code)

295/369
{

case IOCTL_GET_VERSION:

case IOCTL_INTERNAL_GET_SECRET:

// <== exposed for user-mode calls

Nu mt ng dng c th bng cch no xc nh gi tr s ca


IOCTL_INTERNAL_GET_SECRET, n c th pht hnh mt s gi DeviceIoControl
bnh thng v i vng an ton d nh trn chc nng .

Using a Shared Event for Notification

tng c bn ng sau phng php chia s s kin l ng dng to ra mt s kin


bng vic gi l CreateEvent v sau s dng DeviceIoControlto gi ti iu khin
s kin cho b phn iu khin

DWORD junk;

HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

DeviceIoControl(hdevice, IOCTL_REGISTER_EVENT, &hEvent,

sizeof(hEvent), NULL, 0, &junk, NULL);

NOTE Trnh iu khin mu EVWAIT minh ha phng php s kin dng chung ca
vic thng bo mt ng dng v mt s kin th v. Bn pht sinh s kin " th v "
bng vic nhn (nn) mt cha kha trn bn phm, do vic gy ra s th lp trnh
gi l mt IOCTL ca sau trong b phn iu khin. Trong cuc sng thc s, mt bin
c phn cng thc t s pht sinh s kin.

S gi ti CreateEvent to ra a kernel-mode KEVENT object v lm mt mc vo vo


trong qu trnh ng dng x l bng m tr vo KEVENT. Gi tr HANDLE tr li i
vi ng dng thc cht l mt ch s vo trong bng iu khin . iu khin tuy
nhin khng trc tip hu ch i vi mt trnh iu khin WDM, bi hai l do. Trc
ht, khng ly mt ti liu giao din kiu nhn t mt s kin, c a cho
ng (l) mt iu khin . Th hai, v quan trng nht, iu khin ch hu ch trong
mt lung m thuc v cng qu trnh. Nu m trnh iu khin chy trong mt lung

296/369
chuyn quyn ( Nh n thng lm ), n s khng c kh nng i vi s tham kho s
kin bng cch s dng iu khin .

c xung quanh hai vn ny vi s kin iu khin , trnh iu khin phi "


chuyn i " iu khin ti mt con tr ti underlying KEVENT object. x l mt
thao tc iu khin (php ton kim tra) METHOD_BUFFERED ng dng thng
ng k mt s kin vi trnh iu khin, m s dng ging iu ny

HANDLE hEvent = *(PHANDLE) Irp->AssociatedIrp.SystemBuffer;

PKEVENT pevent;

NTSTATUS status = ObReferenceObjectByHandle(hEvent,

EVENT_MODIFY_STATE, *ExEventObjectType, Irp->RequestorMode,

(PVOID*) &pevent, NULL);

ObReferenceObjectByHandle xem hEvent trong bng iu khin (cho) qu trnh


hin thi v ct gi a ch (ca) i tng nhn c lin h trong bin pevent. Nu
RequestorMode trong IRP l UserMode, chc nng ny cng kim tra rng hEvent tht
s l mt iu khin ti ci g , m ci g l mt i tng s kin, v iu
khin c m trong mt cch m bao gm c quyn EVENT_MODIFY_STATE.

Bt c khi no m bn yu cu i tng qun l vin gii quyt mt iu khin thu


c t kiu ngi s dng, s truy nhp yu cu v s kim tra kiu bng vic ch bo
UserMode (cho) i skiu accessor ti i tng qun l vin no vn hnh bn gi
(hng ti). Rt cuc, s bn c t ngi s dng kiu C l khng l mt iu
khin no, hay l n C l l mt iu khin ti kiu khc no (ca) i tng.
Ngoi ra, trnh chc nng undocumented ZwSetEvent Trong mnh lnh khng phi
to ra l an ninh sau y: d l bn chc chn iu khin ngu nhin no (cho) mt
i tng s kin, ngi gi kiu ngi s dng (ca) cc bn c th ng iu
khin v nhn c sau cng iu khin s (cho) mt kiu khc nhau ca i tng.
Bn khng c gy ra ci g xu xy ra v bn l mt ngi gi c th tin cn c
(ca) ZwSetEvent. ng dng c th i s kin xy ra:

WaitForSingleObject(hEvent, INFINITE);

The driver signals the event in the usual way:

KeSetEvent(pevent, EVENT_INCREMENT, FALSE);

Dn dn, ng dng dn sch ln trn bng vic gi l CloseHandle. Trnh iu khin c


mt s tham kho ring bit ti i tng s kin, m n phi gii phng bng vic gi

297/369
l ObDereferenceObject. i tng qun l vin khng c ph hy i tng s kin
cho n khi c hai th ny xut hin.

Using a Pending IOCTL for Notification

tng trung tm trong phng php thng bo IOCTL ang xem xt l khi ng dng
mun nhn c nhng thng bo s kin t trnh iu khin, n giDeviceIoControl:

HANDLE hDevice = CreateFile("\\\\.\\<driver-name>", ...);

BOOL okay = DeviceIoControl(hDevice, IOCTL_WAIT_NOTIFY,

);

(IOCTL_WAIT_NOTIFY, nhn tin, l m iu khin Ti c dng trong mu


NOTIFY trong ni dung hng dn.)

Trnh iu khin cha quyt nh IOCTL ny v hon thnh n sau .Nu nhng xem
xt khc khng xm nhp m trong trnh iu khin c l n gin nh iu ny:

NTSTATUS DispatchControl(...)

switch (code)

case IOCTL_WAIT_NOTIFY:

IoMarkIrpPending(Irp);

pdx->NotifyIrp = Irp;

return STATUS_PENDING;

VOID OnInterestingEvent(...)

298/369
CompleteRequest(pdx->NotifyIrp,

STATUS_SUCCESS, 0); // <== don't do this!

" Nhng s xem xt khc " Ti thy ng nh vy tin li gp li di Thm, tt


nhin, ht sc quan trng crafting mt trnh iu khin ch lm vic.

B khi u (ca) IRP c l quyt nh hy b n. ng dng c l gi l CancelIo,


hay im tn cng (ca) lung ng dng c l gy ra mt thnh phn kiu nhn gi
l IoCancelIrp. Trong mi trng hp, chng ti phi cung cp mt s hy b thng
l IRP c hon thnh. Phi chng sc mnh c loi b t thit b (ca) chng
ta, hoc Nu thit b (ca) chng ta c loi b thnh lnh t my tnh, chng ti c
th mun lm sy (hng) bt k yu cu IOCTL ni bt no. Ni chung, bt k s
lng IOCTLs no c l cn sa sy. Vy th, Chng ti s cn mt bn k lin kt
ca chng. T nhng lung c l ang th truy nhp bn k lin kt ny, chng
ti cng s cn mt s kha quay trn chng ti c th truy nhp danh sch an ton.

Helper Routines

n gin ha cuc sng (ca) ring mnh, Ti vit mt s ng cng (ca) ngi
gip nhng th tc qun l IOCTLs khng ng b. Hai th Quan trng nht ca
nhng th tc ny c tn CacheControlRequest v UncacheControlRequest. H gi thit
iu bn s chp nhn ch c mt IOCTL khng ng b c mt m iu khin c bit
trn thit b phn i v m bn c th, bi vy, d tr mt con tr trong m rng
thit b ch ti IRP iu hin thi ni bt. Trong NOTIFY, Ti gi l con tr
NotifyIrp ny. Bn chp nhn IRP khng ng b cch ny:

switch (code)

case IOCTL_WAIT_NOTIFY:

if (<parameters invalid in some way>)

status = STATUS_INVALID_PARAMETER;

else

status = CacheControlRequest(pdx, Irp, &pdx->NotifyIrp);

break;

299/369
}

return status == STATUS_PENDING ? status :

CompleteRequest(Irp, status, info);

S pht biu quan trng y l s gi ti CacheControlRequest, nhng s ng k


IRP ny trong mt cch m chng ti s c kh nng hy b n sau nu cn thit.
N cng ghi a ch (ca) IRP ny trong thnh vin NotifyIrp (ca) m rng thit b
(ca) chng ta. Chng ti ch i n tr li STATUS_PENDING, ti trng hp no
chng ti trnh hon thnh IRP v n gin tr li STATUS_PENDING cho ngi gi
(ca) chng ta.

NOTE Bn c th d dng khi qut ha s Ti m t cho php mt ng dng


c mt IRP (ca) mi kiu ni bt (cho) mi iu khin m. Thay v vic mang
nhng con tr IRP hin thi vo m rng thit b (ca) cc bn, t chng vo trong
mt cu trc m bn thy lin quan n FILE_OBJECT m tng ng ti iu khin .
Bn s a mt con tr ti FILE_OBJECT ny trong s nh v (v tr) chng I/O (cho)
IRP_MJ_CREATE, IRP_MJ_CLOSE, v, tht ra, tt c IRPs khc sinh ra (cho) iu
khin h s. Bn c th s dng mi FsContext hay lnh vc i tng h s (cho) bt
k (ci) no FsContext2 Bn d nh chn.

Later , khi s kin no ng dng ang i cho xut hin, chng ti thc hin m nh
iu ny

PIRP nfyirp = UncacheControlRequest(pdx, &pdx->NotifyIrp);if (nfyirp)

<do something>

CompleteRequest(nfyirp, STATUS_SUCCESS, <info value>);

Lgic ny khi phc a ch (ca) yu cu IOCTL_WAIT_NOTIFY ang xem xt, m


ci g cung cp d liu quay tr li ng dng, v sau hon thnh gi yu cu I/
O ang xem xt.

How the Helper Routines Work

I hid a wealth of complications inside the CacheControlRequest and


UncacheControlRequest functions. Hai chc nng ny cung cp mt lung v c ch an
ton b a x l theo di nhng yu cu IOCTL khng ng b. H s dng mt s

300/369
bin i trn k thut Chng ti tranh lun ni khc trong sch an ton xp hng v
ra khi hng IRPs i khi mt ngi khc c l ang di ch v vic th hy b
IRP. Ti tht s ng gi nhng th tc ny trong GENERIC.SYS, and mu NOTIFY
trong ni dung hng dn ch ra lm sao gi chng. Heres how those functions work
(but note that the GENERIC.SYS versions have Generic in their names):

typedef struct _DEVICE_EXTENSION {

KSPIN_LOCK IoctlListLock;

LIST_ENTRY PendingIoctlList;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS CacheControlRequest(PDEVICE_EXTENSION pdx, PIRP Irp,

PIRP* pIrp)

KIRQL oldirql;

KeAcquireSpinLock(&pdx->IoctlListLock, &oldirql);

NTSTATUS status;

if (*pIrp)

status = STATUS_UNSUCCESSFUL;

else if (pdx->IoctlAbortStatus)

status = pdx->IoctlAbortStatus;

else

IoSetCancelRoutine(Irp, OnCancelPendingIoctl);

if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))

status = STATUS_CANCELLED;

301/369
else

IoMarkIrpPending(Irp);

status = STATUS_PENDING;

Irp->Tail.Overlay.DriverContext[0] = pIrp;

*pIrp = Irp;

InsertTailList(&pdx->PendingIoctlList,

&Irp->Tail.Overlay.ListEntry);

KeReleaseSpinLock(&pdx->IoctlListLock, oldirql);

return status;

VOID OnCancelPendingIoctl(PDEVICE_OBJECT fdo, PIRP Irp)

KIRQL oldirql = Irp->CancelIrql;

IoReleaseCancelSpinLock(DISPATCH_LEVEL);

PDEVICE_EXTENSION pdx =

(PDEVICE_EXTENSION) fdo->DeviceExtension;

KeAcquireSpinLockAtDpcLevel(&pdx->IoctlListLock);

RemoveEntryList(&Irp->Tail.Overlay.ListEntry);

PIRP pIrp = (PIRP) Irp->Tail.Overlay.DriverContext[0];

302/369
InterlockedCompareExchange((PVOID*) pIrp, Irp, NULL);

KeReleaseSpinLock(&pdx->IoctlListLock, oldirql);

Irp->IoStatus.Status = STATUS_CANCELLED;

IoCompleteRequest(Irp, IO_NO_INCREMENT);

PIRP UncacheControlRequest(PDEVICE_EXTENSION pdx, PIRP* pIrp)

KIRQL oldirql;

KeAcquireSpinLock(&pdx->IoctlListLock, &oldirql);

PIRP Irp = (PIRP) InterlockedExchangePointer(pIrp, NULL);

if (Irp)

if (IoSetCancelRoutine(Irp, NULL))

RemoveEntryList(&Irp->Tail.Overlay.ListEntry);

else

Irp = NULL;

KeReleaseSpinLock(&pdx->IoctlListLock, oldirql);

return Irp;

303/369
1. Chng ti s dng mt s kha quay trn bo v danh sch (ca) IOCTLs ang xem
xt v cng bo v tt c cc con tr m c d tr tr vo th hin hin thi ca
mi yu cu kiu IOCTL khng ng b khc nhau

2. iu ny l ni chng ta Gim st vic thi hnh quy tc-n l ca mt quyt nh thit


k na, tht s-ch c mt IRP (ca) mi kiu c th (th) ni bt ti mt thi gian

3. iu ny nu s pht biu iu tit thc t m chng ti c th cn bt u b qun


u vo IRPs ti im no bi v PnP hay nhng s kin sc mnh.

4. T Chng ti ni vo cui ui IRP ny ci g c l l mt thi gian di, chng


ti cn phi c mt s hy b thng l (cho) n. Ti bn lun lgic hy b rt nhiu
thi gian trong sch ny m Ti cm thy chc chn bn khng kh hn khi c v n
mt ln na.

5. y Chng ti c gii quyt tin ln v cc IRP ny v th m chng ti c


th hon thnh n sau . T Chng ti i n kt lun tr li STATUS_PENDING
t chc nng DispatchControl (ca) chng ta, chng ti cn gi l IoMarkIrpPending.

6. Chng ti cn c mt cch ti NULL ngoi con tr b m khi Chng ti


hy b IRP. T khng c cch c mt tham s vn cnh chuyn cho s
hy b thng l (ca) chng ta , Ti quyt nh kt np mt trong nhng lnh vc
DriverContext trong IRP gi mt con tr ti con tr b m.

7. Trong kha hc bnh thng (ca) nhng s kin, pht biu uncaches l mt IRP.

8. By gi c iu l Chng ti khng c vng nh m IRP ca chng ti, chng ti


khng mun n cancelled bt k (ci) no na. Nu IoSetCancelRoutine tr li NULL
,tuy nhin, chng ti bit IRP ny hin thi trong qu trnh (ca) cancelled.Chng ti tr
li mt con tr NULLIRP trong trng hp .

NOTIFY cng C mt trnh iu khin IRP_MJ_CLEANUP v vic xem xt IOCTLs


m trng th ch ging nh nhng trnh iu khin cleanup Ti tranh lun v
vic c v vit nhng thao tc. Cui cng, n bao gm mt chc nng gip
AbortPendingIoctls trong vic s dng ti thi gian ngt in hay thi gian di chuyn
bt ng, nh sau:

VOID AbortPendingIoctls(PDEVICE_EXTENSION pdx, NTSTATUS status)

InterlockedExchange(&pdx->IoctlAbortStatus, status);

CleanupControlRequests(pdx, status, NULL);

304/369
}

CleanupControlRequests l trnh iu khin IRP_MJ_CLEANUP. Ti vit n theo mt


cch m n hy b tt c IRPs ng ch nu i sth ba-bnh thng mt con tr i
tng tp tin l NULL .

NOTIFY hi qu n gin c dng lm mt m hnh y (cho) mt trnh iu


khin th gii- thc s. y l mt s s xem xt b sung (cho) bn tham kho
trong qu trnh thit k (ca) ring mnh:

_Trnh iu khin c l c vi kiu nhng s kin m thc y thng bo. Bn


c th quyt nh tha thun Vi chng bng cch s dng mt m IOCTL n, trong
trng hp no bn ch bo nhng m IOCTL kiu s kin bi loi no (ca) d liu
ra, hay bng cch s dng nhiu.

_Bn c l mun cho php nhiu lung ng k (cho) s kin. Nu m trng hp,
bn chc chn c mt con tr IRP n trong m rng thit b- bn cn mt cch theo di
tt c IRPs m lin quan ti mt kiu c bit (ca) s kin. Nu bn ch s dng mt
kiu n ca IOCTL (cho) tt c cc thng bo, mt cch kim tra l chng xp hng
trn PendingIoctlList c ch ra trc . Ri, khi mt s kin xut hin, bn thc hin
mt vng m trong bn gi ExInterlockedRemoveHeadList v IoCompleteRequestto
lm trng rng danh sch ang xem xt. (Ti trnh s phc tp ny trong NOTIFY bi
mnh lnh-Ti quyt nh Ti ch chy c mt chng trnh th ti mt thi im.) _S
lin lc IOCTL (ca) Cc bn thng l c trong mt cuc ua vi hot ng m pht
sinh nhng s kin. Chng hn, trong mu USBINT Ti tranh lun trong Chng 12,
chng ti c mt cuc ua tim tng gia th tc lin lc IOCTL v pseudointerrupt
thng l m dch v mt ngt endpoint trn mt thit b USB. Ti vic trnh mt nhng
s kin hay cm ly nhng hot ng mu thun, bn cn mt s kha quay trn. Tham
chiu ti mu USBINT trong ni dung (cho) mt s minh ha ca vic s dng s kha
quay trn nh th no ph hp. (ng b ha khng chy ra trong NOTIFY bi v bng
thi gian mt con ngi (th) c th thc hin nhn phm m th s kin bo hiu, yu
cu thng bo gn nh chc chn ang xem xt. Nu khng phi, yu cu tn hiu c
mt li.).

305/369
Bi 18: THC HNH LP TRNH
DRIVER CHO IU KHIN VO/ RA
Thc hnh lp trnh driver cho iu khin Vora
Bi 1.

Da vo cc iu khin vo ra (I/O) vit 1 driver truyn 1 string ra ngoi cng COM/


LPT sau loopback thng ip v my tnh.

Bi 2.

Vit driver cho ng dng Plug and Play, ng dng : pht hin ra thit b USB khi cn
USB vo my tnh. a ra thng bo c thit b USB-KTMT

306/369
Bi 19: TRNH IU KHIN CHO USB
Gii thiu cng USB
USB - 10 nm ra i

2005 l nm th 10 k t khi phng thc kt ni USB chnh thc ra mt. Phng thc
truyn d liu ny gi tr thnh ph bin trong cng ngh thng tin, vin thng v
in t gia dng. Nhng t ai bit c qu trnh pht trin, nhng thi khc ng nh
cng nh nhng k nim kh qun v n.

USB chi phi cu hnh mng my tnh


truyn thng hin ti v tng lai.
Cc mc son lch s
2005 Gii thiu USB khng dy
2001 Gii thiu USB OTG
USB thc s tr thnh tro lu chnh.
2000
Gii thiu USB 2.0.
Ra mt USB 1.1. Apple gii thiu my
1998
iMac ch s dng cng USB.
C 500 sn phm trang b USB trn ton
1997
cu. USB-IF c 400 thnh vin.

307/369
Sn phm trang b USB u tin ra mt.
1996
Ra mt chun USB 1.0.
Intel gii thiu USB silic u tin. USB-
1995
IF c 340 thnh vin.
1994 Thnh lp nhm cng ty khai sinh USB.

10 nm qua chng kin s hnh thnh v pht trin mt cng ngh truyn dn c
tn gi hin tr thnh rt i quen thuc trong gii truyn thng l kt ni USB
(Universal Serial Bus). Trong nhng nm u tin ra mt, nhiu ngi cho rng USB
khng th tr thnh cng ngh dn u. Ngoi mc ch kt ni cc my tnh v cc
thit b thng tin v vin thng li vi nhau, loi hnh ny nay tr thnh phng tin
truyn dn ph thng nht kt ni thit b ch vi cc thit b ngoi vi, bao gm c
cc thit b in t gia dng. Ngay t khi ra i, USB ng mt vai tr quan trng
trong vic kt ni ca my tnh desktop v cc thit b ngoi vi.

Tiu s ca USB l mt cu chuyn di kh hp dn v c hu. Nm 1995, USB chnh


thc c mt nhm gm 7 hng vin thng, my tnh hng u th gii trnh lng, v
gi y, n tr thnh mt loi hnh kt ni ph qut nht khng ch c ng dng
trong lnh vc cng ngh thng tin m cn c s dng h tr kt ni cho cc thit
b vin thng v in t gia dng. Hin nay, USB tr thnh thn thuc n mc bn
c th d dng thy rng a s cc sn phm in t u c trang b kt ni ny.

Nhm gm 7 i gia tin c USB gia nhp th gii thit b truyn dn d liu
l Compaq, Digital Equipment Corporation (DEC), IBM, Intel, Microsoft, NEC v
Northern Telecom. T khi ra mt USB t cch y 10 nm, DEC b Compaq mua ri
li hp nht vi hng HP (Hewlett Packard). Ngy nay, Hip hi USB (USB-IF) 1.000
thnh vin c nh hng bi cc hng hng u nh Agere, Intel, HP, Microsoft,
NEC v Philips; v trong s ny ch cn li 3 trong 7 hng u cho a con chung
USB t lc khai sinh n gi.

Hng pht trin ca kt ni USB nhn theo logo (t di ln, bn phi sang).

308/369
Khng nh cc giao din kt ni song song (parallel), tun t (serial), PS/2 v cc cng
game thng thng, USB c kh nng thit lp mt loi kt ni ng nht cho tt c
cc thit b ngoi vi trang b USB n my tnh c nhn (PC). V mt l thuyt, ng
truyn n l ny li c th c thay th bng mt khi kt ni USB a cng lp ngoi
cho php ti 127 thit b ngoi vi c th ln lt ni vo mt cng USB n bn ngoi
nh cc HUB USB a cng.

Trong nhng ngy s khai, USB c cc hng u tin hnh th nghim kt ni cc


sn phm vi nhau, thi khc ny tr thnh s kin quan trng m nhng ngi thn
sinh ra USB gi mc s kin lch s ny l Ngy hi kt ni hay Plugfest. S khng
ai tng tng c cm gic ca nhng ngi chng kin i ng kim chng vin lc
, n t hn 50 cng ty thnh vin ca USB-IF trc tip n kim nghim, h h hi
i t phng ny sang phng khc ch chng thc tc phm diu k ny.

Sau , h phi mt 3 ngy cng nhau chnh thc kim th kt ni cc sn phm


USB mi nht vo h thng my ch trung tm. Lc , 10 thit b kt ni thnh cng
vi mt PC m khng h c trc trc hay xung t h thng, cc nh pht trin cng
ngh thc s c th n mng. Thm nhiu thit b khc c ni vi PC chy h iu
hnh Windows. Trong sut qu trnh th nghim, ngi ta thng k c c 127 thit
b kt ni thnh cng vi my tnh, tuy nhin trong s hu ht l chut dng cng
USB.

Biu trng (logo) ca USB qu quen thuc vi cc bn nh ngy nay cng ly i


nhiu thng ca cc n v khai sinh ra n.

Khng ch l kt ni

Ban u, cc nh sn xut PC hng u kh thn trng khng thay th ton b cc cng


ni vn c bng USB, tc l h s dng song song c loi hnh USB mi n v cc kt
ni c truyn. Nm 1998, Apple mnh dn gii thiu dng my tnh iMac, ln u tin
s dng tt c cc kt ni u l USB. H iMac G5 ngy nay cng ch bao gm ton cc
cng USB 2.0 (480 Mb/s) v cc cng Fi-Wi IEEE 1394, nhm h tr tt nht cc ng
dng tc cao.

309/369
Apple iMAC G5 ch s dng kt ni USB v Wi-Fi.

Tuy nhin, hu ht cc my tnh c nhn ngy nay vn c USB v cc cng ni khc


song song tn ti. Bi v cc thit b ngoi vi dng cc cng ni khc USB vn cn rt
ph bin trn th trng v gi thnh ca chng cng hp dn hn.

Mc d ban u tim nng ca USB cha c nh gi mt cch y , nhng ngy


nay cc cng ni USB tr thnh giao din ph bin nht cho hu ht cc ng dng
nh my in, my qut nh, ti nhc MP3, v ng b ho PDA. Hu ht cc PDA ni
ting nh RIM BlackBerry v HP iPAQ, u chn USB l giao tip ng b ho vi
PC.

nh USB 5 GB ca Seagate.

310/369
USB gi y c sc nh hng rt ln ti PC. T nm 2004, hu ht cc nh sn xut
PC u loi b a mm cho cc my tnh bn thay bng c a USB. T lc
, USB v ang tr thnh mt thit b lu tr in hnh l cng USB EZ bus mini
tc cao 20 GB ca Apricorn hay USB b ti 5 GB ca Seagate.

n ri bn phm cng USB ca Kensington.

Kh nng c p dng rng ri nh ngy nay cng nh nhng ng dng ngoi lai
m USB hin ang kim nghim u ngoi s tin on ca Hip hi USB. V d, cng
USB cn c lm thit b ni ngun cho my hm nng cafe, hay dy ngun ca n
bn phm dnh cho my tnh xch tay c Kensington ch to thnh cng. Cc ng
dng hu ch khc ca USB bao gm cc adapter nh iu khin t xa, chuyn i USB
sang Bluetooth, chuyn i USB sang cc cng tun t (serial).

311/369
cng USB ca Apricorn.

Nhiu my tnh s dng h iu hnh Windows ME v XP ca Microsoft u c tch


hp cng USB thay cho cc loi cng thng thng, y cng tr thnh mt hng
pht trin mi ca USB. in hnh l Apricorn tung ra loi cng USB dung lng nh
20 GB. Hng M-Systems cn ra mt loi th nh flash USB u tin thuc loi 100%
cm vo l s dng lun hay cn gi l plug&play. Loi th nh ny t ng nh
dng cu hnh khi cm vo cc PC chy Windows ME/XP, khng cn ci t hay tm
hiu bt k mt phn mm h tr no khc. Trc y, bao gi bn cng phi ci t
mt phn mm driver h tr th mi c th c c d liu lu bn trong th nh.

Th nh USB cn c tch hp vo ng h, vo dao gp, in hnh l tng ca


ngi Thu S vi th nh USB tch hp vo dao gp c tn gi SWISSMEMORY do
cng ty Swissbit cung cp.

Dao gp du lch tch hp th nh USB ca Swissbit.

Ngy nay, USB tr thnh giao din tin ch vi nhiu ng dng khc nhau, cho php lu
tr d liu d dng, gi nh s t camera, d dng kt ni vi my qut nh (scanner),
ti nhc ti my MP3, lu d liu vo th nh ng Steve Whalley, Gim c Tip th
USB 1.0 ca Intel kim chc Ch tch Hip hi USB sut thi gian duy tr cc sn phm
USB chun 1.1, nhc li cha kho thnh cng ca USB: USB c mt khi nim r
rng v c tp trung khai thc cc tnh nng kt ni tin dng thng thng, khi u
t cc kt ni ngoi vi ti PC ri dn dn mi c pht trin, m rng ng dng rng
ri v phong ph nh hin nay.

312/369
Ngy nay hu ht cc my tnh u c trang b mt hoc nhiu cng USB (Universal
Serial Bus). Cc cng USB (USB connector) gip ngi s dng gn mi thit b nh
chut, my in vi my tnh nhanh v d dng hn. Do cc h iu hnh u h tr USB
nn vic ci t cc thit b tht s nhanh v d dng.

So vi cch kt ni cc thit b vi my tnh dng cng song song (Parallel Port), dng
cng ni tip (Serial Port) hay dng cc Card c bit c thit k ci t sn bn trong
my tnh th USB nhanh hn nhiu.

Vi cc my tnh c sn xut vi nm trc y, cc kt ni t thit b ngoi vi ti


my tnh lun lm ngi s dng au u v vn ny c USB c gng gii
quyt:

My in c ni vi my tnh qua cng song song trong khi hu ht cc my


tnh ch c trang b mt cng ny. S rt kh khn nu s dng thm Zip,
lun i hi tc kt ni cao vi my tnh v cn thit phi dng cng song
song.


Modem c ni vi my tnh qua cng ni tip ging nh mt vi dng thit
b khc nh Digital Camera, Palm Pilots trong khi mi my tnh thng ch c
hai cng ni tip v chng rt chm.
Cc thit b i hi cc kt ni nhanh hn nh cc Card c bit c cm trc
tip vo khe cm (Slot) trn bo mch. Thc t s lng cc khe cm (Slot) l c
hn v cn phi ci t cc phn mm cho thit b ny.

313/369
Mc ch ca USB l gii quyt cc vn ca ngi s dng khi cc cng kt ni trn
khng hiu qu. USB cung cp cho ngi s dng kh nng kt ni chun, d dng vi
127 thit b trn cng mt my tnh. Mi thit b ngoi vi hin nay u c th kt ni
trn cng mt phin bn USB chng hn nh: my in, my qut nh, chut, Joystick,
Digital Camera, Webcam, Modem, loa, in thoi, Network Connection, thit b lu
tr thng tin ( Zip)

Vic ni mt thit b vi my tnh qua USB ht sc n gin, ch vic cm cc u ni


ca thit b vi cc cng USB trn my tnh. Nu thit b c kt ni vi my tnh ln
u, h iu hnh s t ng d tm v yu cu np a Driver. Vi thit b c ci
t, my tnh t ng kch hot v kt ni vi thit b. Cc thit b kt ni qua USB c
th thit lp hay ngt kt ni bt k lc no. Nhiu loi thit b USB c ch to lin
vi cp ni vi hai kiu u ni A Connection v B Connection.

Chun USB s dng A Connection v B Connection trong hai trng hp c th


sau:

u ni B Connection dng trong Downstream v ni cc thit b n l


vi my tnh.
u ni B Connection dng trong Downstream v ni cc thit b n l
vi my tnh.

Thng thng cc my tnh hin nay ch c mt hoc hai khe cm USB (USB Socket).
Ngy nay vi a s cc thit b u s dng USB, my tnh rt d b thiu khe cm. V
d, trn my tnh c cc thit b nh: my in, my qut, Webcam, Network Connection
s dng USB trong khi my tnh ch c mt cng USB (USB Connector).

gii quyt vn ny, ch cn lp thm mt USB Hub. Chun USB h tr ti 127


thit b v USB Hub l mt trong s ny. Cc Hub ny thng c bn cng nhng cng
c th c nhiu hn tu thuc tng loi. Ch cn cm USB Hub vo my tnh sau cm
cc thit b hoc Hub khc vo cc cng trn USB Hub.

Hub c hai loi: loi c cung cp ngun v khng cung cp ngun in cho thit b cm
vo Hub. Chun USB cho php cc thit b s dng ngun in t cng USB. Cc thit

314/369
b nh my in, my qut s dng ngun in ring cung cp t b ngun (Power Supply)
ca chng trong khi cc thit b s dng rt t in nng nh chut, Digital Camera li
dng in nng (khong 500mA - 5V) t Bus.

Nu my tnh kt ni vi nhiu thit b s dng ngun in ring (My in, my qut)


th USB Hub khng cn thit phi l loi cung cp c ngun in. Nu my tnh kt
ni vi nhiu thit b khng c ngun in ring (Chut, Digital Camera) th Hub nht
thit phi c kh nng cung cp ngun cho cc thit b ny. Trn Hub c mt b phn
nh bin th cung cp dng in ti Bus v lm my tnh khng b qu ti.

Cc c im ca USB bao gm:

My tnh hot ng nh mt Host.


C ti 127 thit b c th kt ni vo my tnh bao gm c ni trc tip hay qua
USB Hub.
Cc cp USB (USB Cable) ca tng thit b c th di ti 5m hay 30m vi
Hub.
Chun USB2.x cho php truyn d liu trn Bus ti tc 480 Mbps.
Mt cp USB c hai dy cung cp in v mt i dy xon truyn d liu.
Trn dy cung cp in nng, in p c th ln ti 500mA - 5V.
Cc thit b s dng t in nng c cung cp in nng trc tip t Bus. Cc
Hub c th cung cp in nng cho cc thit b ni vi n t ngun in ring
ca chng.
Cc thit b USB c kh nng hon i nhanh, c th cm vo hay rt ra khi
Bus bt k lc no.
Cc thit b USB c th t ch ng (Sleep Mode) khi my tnh chuyn
sang ch Power-Saving.

315/369
Cc thit b ni vi cng USB dng cp USB truyn ti dng in hay d liu. Khi
my tnh hot ng, n truy vn ti tt c cc thit b ni vo Bus v gn cho mi thit
b mt a ch. Qu trnh ny c gi l lit k cc thit b. My tnh cng s tm ra
cch truyn d liu ca tng thit b:

Interrupt: Cc thit b nh bn phm gi lng d liu rt nh v ngt on s


c chn kiu Interrupt Mode.
Bulk: Cc thit b nh my in thng nhn nhng gi d liu ln, dng kiu
Bulk Transfer Mode. Tng on d liu (64 Byte) c gi ti my in v c
kim tra tnh chnh xc.
Isochronous: Cc thit b truyn d liu theo dng Stream nh loa s dng
Isochronous Mode. D liu tc thi c truyn gia thit b v my tnh v
khng c c ch sa li.

My tnh cng c th gi i cc lnh hay truy vn cc thng s vi cc gi Control


Packet. Khi mt thit b c my tnh lit k, my tnh s ginh ti 90% bng thng
(Bandwidth) phc v cc yu cu ca cc thit b kiu Interrupt v Isochronous. Sau khi
dng 90% ca 480 Mbps bng thng, my tnh s t chi cc truy nhp ca bt k thit
b kiu Interrupt hay Isochronous no khc. Cc Control Packet v thit b kiu Bulk
Transfer s s dng khong 10% bng thng cn li.

USB phn chia bng thng thnh cc Frame v my tnh s iu khin cc Frame ny.
Mi Frame cha 1.500 Byte v Frame mi c sinh ra sau mi mili giy. Trong mt
Frame, cc thit b kiu Isochronous v Interrupt phn chia thnh cc khe nn chng
m bo c bng thng cn thit trong khi cc thit b Bulk Transfer v Control
Packet s dng phn bng thng cn li.

Chun USB2.0 xut hin vo thng T nm 2000 v c nng cp t USB1.1. USB2.0


cung cp thm bng thng cho cc ng dng Multimedia v lu tr c tc truyn d
liu ln gp 40 ln so vi USB1.1. vic chuyn t chun USB1.1 sang USB2.0 thun
tin cho c ngi s dng v nh sn xut, USB2.0 c thit k hon ton tng thch
v lm vic c vi cp cng nh cng ni ca thit b USB nguyn thu.

USB2.0 h tr ba ch truyn d liu: 1,5Mbps, 12Mbps v 480Mbps. Ngoi ra


USB2.0 h tr cc thit b bng thng thp nh bn phm v chut cng nh cc thit b
bng thng ln nh Webcam, my in, my qut nh v h thng lu tr.

316/369
Bi 20: THC HNH IU KHIN QUA
CNG USB
Thc hnh vi cc chng trnh v d iu khin qua cng
USB
Bi 1.

Hon thin lp trnh USB bi thc hnh trc (Plug and Play)

Bi 2.

Thc hin truyn, nhn d liu qua cng USB.

317/369
Bi 21: TRNH IU KHIN CHO HID
Nhng b iu khin cho thit b HID (Drivers for HID
Devices )
Lp trnh iu khin cho cc thit b HID ca Microsoft, HIDCLASS.SYS, cung cp
khung tng th cho trnh iu khin WDM qun l cc thit b HID trn tt c cc
nn tng Windows. Microsoft cng cung cp mt trnh iu khin con HIDCLASS tn
HIDUSB.SYS x l cc thit b cm tay USB ca thit b hoc m t giao din ch
ra rng chng thuc v lp HID. Do , nu thit b cm tay USB ca bn thuc cc lp
HID, bn c th khng phi vit mt trnh iu khin c bit cho tt c bi v lp trnh
iu khin Microsoft v minidriver h tr y cc k thut ca USB.

Nu bn ang thit k mt thit b USB trong bao gm mt s chc nng nh HID,


ng qun rng bn c th lm cho n mt bn tng hp thit b nh ngha bi mt s
giao din. c im chung trnh iu khin nguns ring bit cc chc nng ca in
thoi ca bn m h thng s np cc trnh iu khin Microsoft chun cho cc chc
nng HID Microsoft cng cung cp trnh iu khin cho cc chun PS2 ca bn phm v
chut, v cho cng ni tip-chut. Cc trnh iu khin, cng vi HIDCLASS, nm bn
di lp iu khin b lc tn l KBDCLASS v MOUCLASS, m hin ti mt giao
din nht qun thnh phn cp cao hn.

Bn c th cn phi vit mt trnh iu khin con tu chnh thay th HIDUSB.SYS,


nu thit b USB ca bn hoc cung cp giao din hay cu trc bo co dng n nhng
khng thuc vo cc lp HID. Trong trng hp ny, trnh iu khin con( minidriver
)ca bn s cung cp cho mt nhn Faux HID HIDCLASS, v n cng s to ra c
cu ph hp vi cc nhn tng trnh phn ng li cc s kin nhn d liu.

Ngay c vi mt lp thit b HID-USB, bn c th c vit ring ca bn trnh iu


khin con(minidriver) h tr ty chnh cc tnh nng. Ti s dng phng php
tip cn ny xy dng cc trnh iu khin cho mt s thit b c bit, bao gm c
mt con chut chi game vi nhiu nt v n chiu sng v mt u-theo di thit b
cm bin cung cp cc gi tr phi c chuyn i vo cc v tr tng minh. Trong
nhng trng hp ny, cc thit b ang c lp HID ca thit b USB, nhng cc khch
hng mun thc hin cc bo co thit b khc nhau t nhng ci c to ra bi
chng trnh c s. N khng c thc hnh trong cc trng hp ny a cc
tnh nng tu chnh vo chng trnh c s.

Cui cng, nu bn c mt thit b khng h tr USB (khc hn l mt tiu chun bn


phm hoc chut) trong bao gm chc nng nh HID, mt cch ty chnh trnh iu

318/369
khin con HIDCLASS thc t ch l cch lm thit b c th truy cp vo
DirectX v cc ng dng hin c.

319/369
Nhng m t bo co v nhng bo co (Reports and
Report Descriptors )
Mt thit b HID chuyn thng tin trong mt khi c bit n nh l mt bo co. Cc
bo co c cha bit v cc trng nh dng kiu s nguyn theo mt k hiu. Nhiu
c t HID v c im k thut lin quan n ti liu m t ni dung ca cc bo co
v bo co nhn din chi tit. Ti s phn tch hai mu bo co nhn din y gip
bn hiu cc k thut.

Mu nhn din bn phm

bt u vi, ti ngh bn nn ti c gi l HID Descriptor Tool (DT.EXE) t


http://www.usb.org. Cc cng c cho php bn to v chnh sa bo co nhn din bng
cch s dng tn. Hnh 13-1 minh ho cc giao din ngi s dng v mt trong nhng
v d nhn din c sn vi cc cng c.

Hnh 13-1. Bng cch s dng HID Tool xc nh mt bo co nhn din bn


phmMc u tin trong cc mu bo co nhn din c a vo ch yu ch nh mt
tn cho mt s thng s hng s trong cc yu t ca nhn din. Bn cn phi c HID
Usage Tables s dng ti liu gii thch cc s. V d, s dng m s 6 c ngha l
bn phm trong my tnh m phng thit b kim sot trang.

320/369
Th hai, xc nh mc s dng cho cc trang k tip gm c cc trang trong b su tp
nhn din cp cao . Trong c im k thut HID, mt nhm tp hp dch v d liu
lin quan n mc trn. V d, mt nhm tp hp vt l thu thp ti mt im hnh hc,
trong khi mt nhm tp hp ng dng cng c th lin h vi cc ng dng. Mt khi
nim thm na, nhng tp hp logic, cho php lin quan n mc c nhm vo bn
trong mt cu trc d liu hp li, chng hn nh mt byte d liu truy cp k tip.
Nhng khi nim tru tng nh vy l c gn v ngha, v Microsoft v ngha
gn thm, nh sau:

Mt tp hp u mc, chng hn nh bt u bng mt trong nhng mc th ba trong


bn phm mu, tng ng vi mt t chc a ch ring r. Hnh ng nh l mt knh
ca thit b, HIDCLASS to ra mt i tng vt l (PDO) cho mi tp cc u .Cc
thit b nh danh cho tp hp bao gm ID tng thch, da trn cc m s dng. Xem
Bng 13-1. Nu tp hp no khc s dng, HIDCLASS s khng to ra mt ID tng
thch. Tham kho Chng 15 bit thm thng tin v tm quan trng ID tng thch
trong vic np trnh iu khin. PDO sau tr thnh c s ca mt ngn xp thit b
PnP cho mt s loi thit b. Ch rng nhiu tp u mc nh hng n nhiu ngn
xp thit b. Trong lm vic thc t, cc thit b phi s dng bo co nhn din phn
bit gia cc tp khc nhau.

Mt tp lin kt l mt trong nhng tp mc u cp. Lin kt cung cp mt b su


tp ca t chc Hierarchy rng cc ng dng c th s dng kim sot nhm lin
quan trong mt thit b phc tp. Trn mt game pad, v d, mt b su tp c th s
dng lin kt phn bit gia cc nt actuated do bn tri v tay phi. C v t im
tng qut ny, tuy nhin, khi kt thc ng dng thng yu cu ngi dng n nh
ngha kim sot da trn con s hn l v tr trong mt Hierarchy. Nhng c l ti
ch nhn thy khng c cc ng dng v thit b HID to ra mt bn n, ton din.

Bng 13-1. HIDCLASS-tng ID cho mi h tr s dng

S dng trang s dng tng id

Chung loi my tnh bn Pointer hay chut HID_DEVICE_SYSTEM_MOUSE

Bn phm hay bn phm HID_DEVICE_SYSTEM_KEYBOARD

Phm iu khin hay game pad HID_DEVICE_SYSTEM_GAME

H thng kim sot HID_DEVICE_SYSTEM_CONTROL

Tiu dng (Bt k) HID_DEVICE_SYSTEM_CONSUMER

Trong n cp u cho b su tp cc mu bn phm, quan trng nht l nhng bi


chnh, tn l bi ng gp v cc OUTPUT. Mt yu t u vo mc tng ng vi

321/369
mt trng u vo trong mt bo co, trong khi mt mc OUTPUT tng ng vi mt
lnh vc sn xut trong mt bo co. Hin cng c th c dng xc nh c im
bi trong lnh vc bo co mt tnh nng, nhng bn phm mu khng bao gm bt k
ngi trong s h. Mt s bi ton cu vic chnh trong bi m t cc bn trnh by
v ngha ca cc d liu ring ca mnh.

iu quan trng l phi nhn thy l input, OUTPUT, v c im bi bo co c th


c Interleaved trong bo co descriptor. Cc b su tp cu trc logic trong mt cp
cao b su tp khng phi l quan trng trong xc nh bn ghi d liu xut hin
cng nhau trong mt bn bo co. Thay vo , cc loi hnh cc mc qun l quyn.
Do , v d bn phm descriptor mixes OUTPUT ng gp v cc bi trong mt cch
m c th ngh rng c cc bo co nm, hoc mt ngi no khc bidirectional bo
co. Trong thc t, c mt u vo bo co xc nh bi cc INPUT bi v sn lng
mt bo co c xc nh bi cc bi OUTPUT.

Cc bi chnh, cng vi tt c cc bi iu kin ton cu, xc nh cc bit, b tr ca


mt cu trc bo co. hnh dung bo co, chuyn nhng quyn t bit bn tri v
khng li bt k bit khng s dng cho mc ch alignment. Multibit cha tr cho
cc gi tr, bao gm c nhng ngi span byte ranh gii, nh t v cui (t nht ng k
bit trn bn phi ca kt qu hnh nh). Chia kt qu vo byte, m cc thit b truyn t
quyn bn tri.

Trong bo co bn phm, chng ti nm bn ghi d liu trong b su tp, v h xc


nh mt yu t u vo bo co v mt bo co sn lng (xem Hnh 13-2):

An u vo mc gm tm (REPORT_COUNT) single-bit, gi tr (REPORT_SIZE


1), mi phng trong s c th thay i t 0 (LOGICAL_MINI Mum) ti
1 (LOGICAL_MAXIMUM). ngha ca cc bit tng ng vi bn phm Usages
(USAGE_PAGE) E0 thng qua E7 (USAGE_MINI Mum v USAGE_MAXIMUM).
Ni cch khc, byte 0 u vo ca cc bo co c cha bit c ch ca chuyn i
c cu kinh-loi phm trn bn phm hin ang chn nn.

A c nh u vo mc gm mt (REPORT_COUNT) 8-bit, gi tr (REPORT_SIZE).


y l 1 trong byte u vo bo co, v iu ch n gin l mt ch c cha d liu
khng hp l.

An sn lng sn phm bao gm nm (REPORT_COUNT) single-bit


(REPORT_SIZE) gi tr. Cc LOGICAL_MINIMUM v ng CAL_MAXIMUM
gi tr trc xc nh p dng cho nhng gi tr, v h khng c ghi e.
ngha ca cc bit l khc nhau, tuy nhin: h tng ng vi LEDs (USAGE_PAGE)
vi cc nhn nh ln Lock (USAGE_MINIMUM v LOGICAL_MAXI Mum). Ni
cch khc, cc lnh thp 5-bit ca byte 0 sn lng ca cc bo co cha c
kim sot LEDs cho toggling phm. A c nh sn lng sn phm bao gm mt

322/369
(REPORT_COUNT) 3-bit (REPORT_SIZE) c gi tr. Nhng 3 bit pad ra, sn lng
t n mt bo co y byte. An u vo mc gm su (REPORT_COUNT)
8-bit, gi tr (REPORT_SIZE), khc nhau, t 0 thng qua 101 (LOGICAL_MINIMUM
v LOGICAL_MAXIMUM) v tng ng vi phm trn mt tiu chun 101-Kha
bn phm (USAGE_PAGE, USAGE_MINIMUM, v USAGE_MAXIMUM). Ni cch
khc, 2 byte thng qua 7 ca cc u vo cha cc m s bo co cho n su phm m
khng c s ng thi t chc xung.

Hnh 13-2. Giao din ca bn phm u vo v sn lng cc bo co.

HIDFAKE Descriptor

Hnh 13-3 minh ho bo co descriptor c s dng trong cc mu HIDFAKE driver


trong phn ni dung. Descriptor bo co ny c mt s tnh nng c khc nhau t bn
phm mu:

Cc n xin cp u ca cch s dng l "Gun thit b" t Gaming Kim sot trang.
iu ny c nhn to mt s la chn m ti lm trnh gp kh khn ci
t trnh iu khin mu. i vi bt k cch s dng c lit k trong bng 13-1,
HIDCLASS s cung cp mt thit b tng thch nh danh cng vi cc thit b c
th ca ID. Windows XP s thch, sau l mt k kt ph hp vi trnh iu khin
tng thch vi mt ID unsigned driver (nh HIDFAKE.SYS) ph hp vi cc thit b
c th ca ID. (Xem Chng 15 cho bit thm thng tin v cch chn trnh iu khin
Windows XP.) It's impossible gn chuyn i sang trnh iu khin c th.

323/369
Ti s dng trong vng ba l b su tp ca chnh b su tp. Cc b su tp logic
ch phc v nh du ba-bo co ca cc c cu descriptor. Cc mu s lm vic hon
ho cng khng c h.

Cc descriptor bao gm mt yu t u vo hai tnh nng bo co v cc bo co. Cc


u vo bo co (1) c cha mt nt s dng. L ngi u tin tnh nng bo co (2)
l tr li cho mt s phin bn trnh iu khin, v th hai, tnh nng bo co (3) l, cho
php cc th nghim dng kim sot tnh trng ca hng gi nt.

Hnh 13-3. Bng cch s dng HID Cng c xc nh HIDFAKE bo co descriptor.


HIDFAKE minh ho mt im tt v bo co descriptors. Bo co kh nhiu tnh nng
cn phi c xc nh s in thoi, v cc c im k thut HID cuc gi cho chng
trong Get_Report_Request v kim sot Set_Report_Request ng lnh. Nu c bo co
trong mt cp cao b su tp c mt nh danh, tt c cc bo co rng trong b su tp
phi. Trong thc t, mc d, HIDFAKE mt m hnh notional in thoi thc s l
mt nt bo co v khng c tnh nng bo co. Ti xc nh cc tnh nng bo co nh

324/369
mt cch kim tra dng giao tip "out of band" vi driver. Nu chng ti c
giao dch vi mt thit b thc t, do , driver s c mt bo co chn nh danh
mi u vo bo co m n c t in thoi.

325/369
Nhng iu khin nh HIDCLASS (HIDCLASS
Minidrivers)
Nh trc y tho lun, Microsoft cung cp mt trnh iu khin (HIDUSB.SYS)
cho bt k thit b USB c xy dng theo HID c im k thut. Phn ny m t
cch bn c th xy dng mt HIDCLASS minidriver cho mt s cc loi in thoi m
bn mun c masquerade nh HID.

DriverEntry DriverEntry cc chc nng cho mt HIDCLASS minidriver l tng t


rng trong mt trnh iu khin WDM thng xuyn, nhng ch ln n mt
im. Trong thi quen ny, bn khi to cc DRIVER_OB JECT cu trc d liu
vi kt n AddDevice v DriverUnload thi quen cng nh dispatch thi quen
cho ch cn ba loi I / O yu cu gi (IRP): IRP_MJ_PNP, IRP_MJ_POWER, v
IRP_MJ_INTERNAL_DEVICE_CON TROL. Sau , bn xy dng mt c cu
HID_MINIDRIVER_REGISTRATION v gi HidRegister Mini driver, l mt
trong nhng chc nng xut khu do HIDCLASS.SYS. Bng 13-2 m t cc lnh vc
trong HID_MINIDRIVER_REGI STRATION c cu.

Bng 13-2. Lnh vc trong HID_MINIDRIVER_REGISTRATION C cu t chc Tn


trng M t

Revision (ULONG) Minidriver b lnh vc ny HID_REVISION, m hin nay bng


1. DriverObject (PDRIVER_OBJECT) Minidriver b lnh vc ny cho cng mt gi tr
nh thng qua cc i s DriverObject DriverEntry.

RegistryPath (PUNICODE_STRING) Minidriver b lnh vc ny cho cng mt gi tr


nh thng qua cc i s RegistryPath DriverEntry.

DeviceExtensionSize (ULONG) Kch thc trong byte ca in thoi m rng c cu


s dng bi cc minidriver.

DevicesArePolled (BOOLEAN) TRUE nu minidriver ca cc thit b cn phi c


hi cho cc bo co. FALSE nu cc thit b spontaneously khi gi bo co d liu s
tr thnh hin c.

Cc trng ch c ngha l khng hon ton thng thn l DevicesArePolled c. Hu


ht cc thit b spontaneously s to ra mt bn bo co kt thc bt c khi no ngi
s dng, khng c g g , v h s thng bo cho cc my ch lu tr thng qua mt
s loi gin on. Cho cc loi in thoi ny, bn thit lp cc DevicesArePolled c
FALSE. HIDCLASS sau s c gng gi hai IRPs (gi l ping-pong IRPs) ang
hot ng c bo co. Minidriver mong mun ca bn l xp hng v hon tt
cc IRPs h trong t hng khi in thoi interrupts.

326/369
Mt s thit b khng spontaneously to ra cc bo co. i vi cc loi thit b, thit
lp cc DevicesArePolled c TRUE. HIDCLASS sau s vn IRPs c bo
co trong mt thi gian loop. Minidriver ca bn c bo co d liu t in thoi ch
phn ng li mi IRP. cp cao hn cc thnh phn, chng hn nh mt ng dng bng
cch s dng giao din DirectX, c th ch nh cc polling chuyn. Ngh rng hai ln
trc khi ci t DevicesArePolled TRUE: hu ht cc thit b cn thit n c
FALSE. y l v d gn hon thnh ca DriverEntry chc nng trong mt HIDCLASS
minidriver:

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,

PUNICODE_STRING RegistryPath)

DriverObject->DriverExtension->AddDevice = AddDevice;

DriverObject->DriverUnload = DriverUnload;

DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =

DispatchInternalControl;

DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;

DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;

HID_MINIDRIVER_REGISTRATION reg;

RtlZeroMemory(&reg, sizeof(reg));

reg.Revision = HID_REVISION;

reg.DriverObject = DriverObject;

reg.RegistryPath = RegistryPath;

reg.DeviceExtensionSize = sizeof(DEVICE_EXTENSION);

reg.DevicesArePolled = FALSE; // <== depends on your hardware

return HidRegisterMinidriver(&reg);

327/369
Driver gi li thi quen

HIDCLASS hot ng cng nh cch ny, nhng vi mt twist. Khi bn gi


HidRegisterMinidriver, HIDCLASS ci t chc nng ring ca mnh trong tr
DRIVER_OBJECT ca bn, cng ging nh hu ht cc lp hc s trnh iu khin.
Thay v s dng mt b c thi quen gi a ch ca bn minidriver cung cp trong
HID_MINI DRIVER_REGISTRATION c cu (khng c), n ghi nh cc thit b
v Thm vo DriverUnload tr v a ch ca bn dispatch thi quen cho PNP, lc,
v yu cu INTERNAL_DEVICE_CONTROL . Nhng thi quen nh driver khng
c chnh xc cng mt chc nng nh t tn nh-thi quen thng xuyn trong WDM
trnh iu khin, mc d. Ti s gii thch trong phn ny nh th no vit gi li
nhng thi quen. AddDevice goi

Cc AddDevice gi trong mt HIDCLASS minidriver c mt tin tng t m


AddDevice thng xuyn ca mt chc nng:

NTSTATUS AddDevice (PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT


fdo); C hai khc bit quan trng gia cc minidriver gi thng xuyn v cc chc
nng:

Cc thit b i tng lun cp n mt chc nng in thoi i tng (FDO) m


HIDCLASS to ra.

Vn khc thc ca FDO l con tr DeviceExtension l a ch ca mt cu


trc m rng iu l b mt i vi HIDCLASS. Vi thnh vin u tin ca iu
cu trc ring c v bn bi cu trc HID_DEVICE_EXTENSION trong DDK:

typedef struct _HID_DEVICE_EXTENSION {

PDEVICE_OBJECT PhysicalDeviceObject;

PDEVICE_OBJECT NextDeviceObject;

PVOID MiniDeviceExtension;

} HID_DEVICE_EXTENSION, *PHID_DEVICE_EXTENSION;

tm thy thit b m rng ca cc bn, bn phi i theo sau dy chuyn con tr ny:

PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) ((PHID_DEVICE_EXTENSION)

(fdo->DeviceExtension))->MiniDeviceExtension;

328/369
Bn s dng cng trnh tng t c c nhng PDO a ch v c c nhng
g ti gi cho LowerDeviceObject trong cun sch ny. (HIDCLASS cuc gi l mt
NextDeviceObject.) L mt li typist, ti thng xc nh macros lm cho cuc
sng ca ti d dng hn trong khi ti ang vit minidriver:

#define PDX(fdo) ((PDEVICE_EXTENSION) ((PHID_DEVICE_EXTENSION) \

((fdo)->DeviceExtension))->MiniDeviceExtension)

#define PDO(fdo) (((PHID_DEVICE_EXTENSION) ((fdo)->DeviceExtension)) \

->PhysicalDeviceObject)

#define LDO(fdo) (((PHID_DEVICE_EXTENSION) ((fdo)->DeviceExtension)) \

->NextDeviceObject)

Bng cch s dng cc macros v trc fragment ca mt DEVICE_EXTENSION c


cu, ca bn minidriver's AddDevice gi c th hnh nh th ny:

NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT fdo)

PDEVICE_EXTENSION pdx = PDX(fdo);

NTSTATUS status = STATUS_SUCCESS;

<initialization code for DEVICE_EXTENSION members>

pdx->AddDeviceStatus = status; // <== whatever is left over

return status; // in case you're running in >= XP

im li mt thc t tnh trng m t AddDevice l trong Windows XP v cc h thng


sau ny, HIDCLASS s khng thnh cng ring ca mnh AddDevice gi nu bn lm
g, v s ngn mch cc s khi ca in thoi ca bn. Nhng k t khi HIDCLASS
khng mng bit m trong cc phin bn c ca h iu hnh, bn cn phi cung cp
mt cch cho StartDevice chc nng ca bn tr v mt m li.

C hai trng hp ngoi l:

329/369
IRP_MN_START_DEVICE handler nhu cu ca bn kim tra li bng cch t
c ca bn AddDevice gi (ti gi l n AddDeviceStatus trong sm hn fragment) v
tht bi trong IRP nu c cho bit mt li. y l cch bn i ph vi thc t l
nhng HIDCLASS khng mng bit cc m t AddDevice tr li trong phin bn ca
Windows trc khi Windows XP.

IRP_MN_REMOVE_DEVICE handler ca bn khng gi IoDetach thit b hay


IoDeleteDevice. Thay vo , n phi ch n gin pht hnh bt k ngun ti nguyn
c phn b bi cc AddDevice gi. HIDCLASS chnh n s chm sc detaching
v xa cc FDO.

Cc mu HIDFAKE driver s dng GENERIC.SYS. DispatchPnp thi quen ca n do


trng nh th ny:

NTSTATUS DispatchPnp(PDEVICE_OBJECT fdo, PIRP Irp)

return GenericDispatchPnp(PDX(fdo)->pgx, Irp);

Ngoi bng cch s dng PDX v m xc nh v tr ca thit b m rng c cu, m


ny cng ging nh s xut hin trong mt chc nng thng xuyn s dng trnh iu
khin GENERIC.SYS. Cc RemoveDevice, StartDevice, v StopDevice ang c chc
nng khc nhau t nhng ngi thn thng xuyn, mc d:

VOID RemoveDevice(PDEVICE_OBJECT fdo)

NTSTATUS StartDevice(PDEVICE_OBJECT fdo,

PCM_PARTIAL_RESOURCE_LIST raw,

PCM_PARTIAL_RESOURCE_LIST translated)

PDEVICE_EXTENSION pdx = PDX(fdo);

if (!NT_SUCCESS(pdx->AddDeviceStatus))

330/369
return pdx->AddDeviceStatus;

return STATUS_SUCCESS;

VOID StopDevice(PDEVICE_OBJECT fdo, BOOLEAN oktouch)

HIDFAKE chnh n khng c m s ti cc im c nhn A, B, v C. Nu bn s dng


mu ny nh l mt mu cho minidriver ring ca bn, bn s vit m thc hin nh
sau: A. Xa cc bt k ngun ti nguyn (chng hn nh b nh, lookaside danh sch,
v nh vy trn) phn b AddDevice. HIDFAKE khng c ngun ti nguyn nh vy.

B. nh cu hnh cc thit b nh tho lun trong chng trc. HIDFAKE khng c


phn cng v do khng c g lm trong bc ny.

C. Deconfigure in thoi do reversing cc bc thc hin trong StartDevice. K t


HIDFAKE khng c g, khng c g trong StartDevice, n khng cn phi lm bt c
iu g y c hai.

DispatchPower goi

Bn ch r DispatchPower gi nh nu n l nhng thi quen cho dispatch


IRP_MJ_POWER, bng cch t mt yu t trong mng, driver ca i tng
MajorFunction bng. HIDCLASS cuc gi ca bn gi nh l mt subroutine trong khi
x l IRPs quyn lc ca nhiu loi. Trong a s trng hp, bn nn ch cn gi qua cc
IRP xung tip theo bng driver m khng thc hin bt k hnh ng v HIDCLASS
c tt c cc qun l ngun in h tr cn thit do cc thit b tiu biu (bao gm c
WAIT_WAKE h tr).

Nu bn t ra DevicesArePolled c FALSE trong cuc gi ca qu v


HidRegisterMinidriver, HIDCLASS s hy b cc ping-pong IRPs trc khi chuyn
tip mt my in yu cu lm gim sc mnh. Nu bn c mt cch n gin
piggybacked trn nhng IRPs gi yu cu thm xung PnP stack, do bn s khng
cn phi lo lng v vic hu b chng. Nu bn c b nh m IRPs n nhng ni no,
bn nn cung cp cho hy b mt thi quen.

Ch thch:

331/369
Nu bn minidriver s dng GENERIC.SYS, cn nhc vic s dng cc
GenericCacheControlRequest v GenericUncacheControlRequest chc nng theo
di IRPs rng bn pend. Cc chc nng ny bao gm cc chng tc-an ton hy b logic.
y l mt v d ca callback DispatchPower trong mt HIDCLASS minidriver:

NTSTATUS DispatchPower(PDEVICE_OBJECT fdo, PIRP Irp)

PDEVICE_EXTENSION pdx = PDX(fdo);

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

IoCopyCurrentIrpStackLocationToNext(Irp);

if (stack->MinorFunction == IRP_MN_SET_POWER

&& stack->Parameters.Power.Type == DevicePowerState)

DEVICE_POWER_STATE newstate =

stack->Parameters.Power.State.DeviceState;

if (newstate == PowerDeviceD0)

IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)

PowerUpCompletionRoutine, (PVOID) pdx, TRUE, TRUE, TRUE);

else if (pdx->devpower == PowerDeviceD0)

// TODO save context information, if any

pdx->devpower = newstate;

332/369
}

return PoCallDriver(LDO(fdo), Irp);

NTSTATUS PowerUpCompletionRoutine(PDEVICE_OBJECT fdo, PIRP Irp,

PDEVICE_EXTENSION pdx)

// TODO restore device context without blocking this thread

pdx->devpower = PowerDeviceD0;

return STATUS_SUCCESS;

1. Bn khng cn phi lm bt c iu g c bit vi bt k quyn lc IRP ngoi


tr mt SET_POWER cho mt thit b quyn lc nh nc.
2. Khi khi phc li quyn lc, bn ci t mt thi quen hon tt trc khi
chuyn tip cc IRP xung stack.
3. Khi xo b quyn lc, bn tit kim bi cnh bt k thng tin trc khi chuyn
tip cc IRP. i ph vi nhng kh nng c th thp hn HIDCLASS rng
sc mnh trong bc (v d, ln u tin sau D2 v D3), bn cng cn phi
theo di ca cc thit b hin quyn lc nh nc. Hay khng in thoi ca
bn c bi cnh thng tin tit kim, iu ny cng l thi gian hy b bt
k chi nhnh IRPs rng driver ca bn ban hnh, chm dt polling threads,
and so on. HIDCLASS bn s c gi in thoi ti khch sn
PASSIVE_LEVEL trong mt h thng si rng bn ang c cho php
chn nu cn thit trong khi thc hin cc nhim v.
4. Nh thng l, bn gi PoCallDriver chuyn tip cc IRP. Bn khng cn
phi gi PoStartNextPowerIrp v HIDCLASS lm nh vy.
5. Cc thng c gi l hon thnh ch sau khi hon thnh mt ti x xe but
t-D0 hot ng. in thoi ca bn c repowered, v bn c th o
ngc cc bc bn thc hin khi bn xo b quyn lc. K t khi bn ang c
kh nng chy t DISPATCH_LEVEL v trong mt si arbitrary, tuy nhin,
bn cn phi thc hin cc bc sau m khng ngn chn hin nay si.
DispatchInternalControl goi

Bn ch r DispatchInternalControl gi nh nu n l nhng thi quen cho dispatch


IRP_MJ_INTERNAL_DEVICE_CONTROL, bng cch t mt yu t trong mng,

333/369
driver ca i tng MajorFunction bng. HIDCLASS cuc gi ca bn nh l mt thi
quen gi subroutine c bo co v cc thng tin khc hoc cung cp hng dn
minidriver ca bn. Bn c th gi chng trnh ny nh th n l mt thi quen bnh
thng IRP dispatch x l s kim sot m s lit k trong bng 13-3.

Bng 13-3. HIDCLASS Minidriver kim sot hot ng

M t kim sot ni b M s

IOCTL_GET_PHYSICAL_DESCRIPTOR Gets USB-tiu chun vt cht descriptor

IOCTL_HID_GET_DEVICE_ATTRIBUTES tr li thng tin v cc thit b nh th n


l USB

IOCTL_HID_GET_DEVICE_DESCRIPTOR tr li mt tiu chun USB-HID


descriptor IOCTL_HID_GET_FEATURE ln c mt tnh nng bo co

IOCTL_HID_GET_INDEXED_STRING tr li mt tiu chun USB-string descriptor


IOCTL_HID_GET_STRING tr li mt tiu chun USB-string descriptor
IOCTL_HID_GET_REPORT_DESCRIPTOR tr li mt bo co tiu chun-USB
descriptor C IOCTL_HID_READ_REPORT ln c bo co conforming bo co
descriptor IOCTL_HID_SEND_IDLE_NOTIFICATION Idles in thoi (mi trong
Windows XP) IOCTL_HID_SET_FEATURE v mt tnh nng bo co

IOCTL_HID_WRITE_REPORT v mt bo co

Ni IOCTL giao din

Cc giao din gia HIDCLASS v mt minidriver l thng qua cc


DispatchInternalControl gi tng kt cui ca phn trc ngy gi thi quen. Trong
phn ny, ti s m t lm th no thc hin mi phng trong s hot ng kim
sot, theo th t trong HIDCLASS bnh th tc by cho h. Lu rng HIDCLASS
khng gi ny cho n khi gi ti tt c cc minidriver sau khi hon thnh mt
IRP_MN_START_DEVICE yu cu.

IOCTL_HID_GET_DEVICE_ATTRIBUTES HIDCLASS gi mt yu cu
IOCTL_HID_GET_DEVICE_ATTRIBUTES l mt phn ca cc ch bin ca
IRP_MN_START_DEVICE yu cu v conceivably, vo nhng thi gian khc, c
c thng tin rng mt thit b USB cc bn ghi trong mt lot cc thit b descriptor.
UserBuffer cc lnh vc ca IRP im n mt d sau y ca cc c cu, m bn nn
hon tt:

typedef struct _HID_DEVICE_ATTRIBUTES {

334/369
ULONG Size;

USHORT VendorID;

USHORT ProductID;

USHORT VersionNumber;

USHORT Reserved[11];

} HID_DEVICE_ATTRIBUTES, * PHID_DEVICE_ATTRIBUTES;

V d, bn c th hon tt cc c cu trong bi cnh ca cc skeletal


DispatchInternalControl hin th sm hn thng l:

case IOCTL_HID_GET_DEVICE_ATTRIBUTES:

if (cbout < sizeof(HID_DEVICE_ATTRIBUTES))

status = STATUS_BUFFER_TOO_SMALL;

break;

#define p ((PHID_DEVICE_ATTRIBUTES) buffer)

RtlZeroMemory(p, sizeof(HID_DEVICE_ATTRIBUTES));

p->Size = sizeof(HID_DEVICE_ATTRIBUTES);

p->VendorID = 0;

p->ProductID = 0;

p->VersionNumber = 1;

#undef p

info = sizeof(HID_DEVICE_ATTRIBUTES);

335/369
break;

Nu in thoi ca bn l nonstandard ch n gin l mt thit b USB, iu r rng


cc gi tr m bn nn cung cp cho cc VendorID, ProductID, v VersionNumber lnh
vc ny c cu: cc idVendor, idProduct, bcdDevice lnh vc v thc s t in thoi
descriptor. Nu in thoi ca bn isn'ta thit b USB, bn cn phi i ln vi dummy
gi tr. Ti s dng 0, 0, v 1, tng ng, trong m ny fragment, v nhng s la
chn s cho tt c cc loi hnh HID thit b ngoi tr mt phm iu khin. c
mt phm iu khin in thoi, bn cn phi chn duy nht gi tr ph hp vi nhng g
bn ch nh trong ng k subkey OEM bn to ra cho cc phm iu khin. Ti khng
c t vn v vic lm th no chn nhng gi tr.

M ra mt b su tp giu trong ch Thnh vin

M ra mt b su tp HID x l cc thnh vin trong ch chnh n l n


gin nu bn ch nh duy nht gi tr cho cc VendorID v ProductID lnh vc
ca HID_DEVICE_ATTRIBUTES c cu. Gi, v d, cc cng ty ca bn s hu
USB bn hng rong ID 0x1234 v rng bn c giao cho 0x5678 ID sn phm
in thoi ca bn. Bn s s dng nhng gi tr khi tr li cu
IOCTL_HID_GET_DEVICE_ATTRIBUTES yu cu.

MFC l mt ng dng s dng cc lp hc CDeviceList cp n trong Chng 2 c


th m ra mt x l mt trong nhng b su tp driver ca bn bng cch tip xc
vi cc m nh sau y (xem cc chng trnh TEST HIDFAKE mu i km vi trnh
iu khin):

HANDLE CtestDlg::FindFakeDevice()

GUID hidguid;

HidD_GetHidGuid(&hidguid);

CDeviceList devlist(hidguid);

int ndevices = devlist.Initialize();

for (int i = 0; i < ndevices; ++i)

336/369
HANDLE h = CreateFile(devlist.m_list[i].m_linkname, 0,

FILE_SHARE_READ FILE_SHARE_WRITE, NULL,

OPEN_EXISTING, 0, NULL);

if (h == INVALID_HANDLE_VALUE)

continue;

HIDD_ATTRIBUTES attr = {sizeof(HIDD_ATTRIBUTES)};

BOOLEAN okay = HidD_GetAttributes(h, &attr);

CloseHandle(h);

if (!okay)

continue;

if (attr.VendorID != HIDFAKE_VID

attr.ProductID != HIDFAKE_PID)

continue;

return CreateFile(devlist.m_list[i].m_linkname,

GENERIC_READ GENERIC_WRITE, 0, NULL,

OPEN_EXISTING, 0, NULL);

return INVALID_HANDLE_VALUE;

1. HidD_GetHidGuid s dng xc nh giao din ton cu nhn bit duy nht


(GUID) cho cc thit b HID.
2. Chng ti enumerate tt c cc thit b HID. Trong thc t, cc Enumeration
khng bao gm cc thit b tiu chun, nh con chut v bn phm.
3. M ra mt cch x l ny (m khng c quyn truy cp y quyn v cho
php chia s) cho php chng ti vn truy vn. Khng ging nh hu ht cc

337/369
trnh iu khin thit b, HIDCLASS tr gn quan tm n quyn truy cp v
chia s vi IRP_MJ_CREATE thuc tnh c xc nh, v chng ti ang li
dng cc tnh linh hot m rng hnh vi to ra bng cch m ra mt mt thit b
x l c th khng thc s c th truy cp c vi mt bnh thng m .
4. HidD_GetAttributes tr v mt thuc tnh c cu thu c t cc
HID_DEVICE_ATTRIBUTES in vo bi cc minidriver.
5. y l tuyn b quan trng trong v d ny. Nu in thoi v ID sn phm ph
hp vi nhng g chng ti ang tm kim, chng ti s b thuc l qut cc
thit b v m mt thc t x l mt ny.
6. iu ny s m ra cuc gi n CreateFile c quyn, nonoverlapped x l cho
c v vit. y l quyn hnh ng cho cc th nghim ca HIDFAKE dng
thc hin. Bn c th chia s cho cc yu cu khc nhau, quyn truy cp,
chng cho v I / O. Lu rng cc cuc gi n CreateFile c th b tht bi,
thm ch nu trc mt thnh cng, nu c mt ng dng khc, m snuck
trong mt x l.

ng dng ca bn c th tm hiu thm phc tp, nu in thoi ca bn c nhiu hn


mt cp u thu thp hoc nu bn cn phi cung cp cho nhiu hn mt d ca phn
cng ca bn.

HIDCLASS gi mt yu cu IOCTL_HID_GET_DEVICE_DESCRIPTOR l mt phn


ca cc ch bin ca IRP_MN_START_DEVICE yu cu v conceivably, vo nhng
thi gian khc, c c mt m t ca in thoi ca HID c im. UserBuffer cc
lnh vc ca IRP im n mt d ca mt tiu chun USB-HID descriptor c cu, m
bn nn hon tt:

typedef struct _HID_DESCRIPTOR {

UCHAR bLength;

UCHAR bDescriptorType;

USHORT bcdHID;

UCHAR bCountry;

UCHAR bNumDescriptors;

struct _HID_DESCRIPTOR_DESC_LIST {

UCHAR bReportType;

USHORT wReportLength;

338/369
} DescriptorList [1];

} HID_DESCRIPTOR, * PHID_DESCRIPTOR;

Mc d, r rng tng qut ca cu trc ny, hin nay HIDCLASS tr y cc


khng gian cho ch c mt yu t trong DescriptorList mng, v n phi c bo co
descriptor. Pht trin ca Microsoft khuyn bn nn kim tra cng tc song le kch c
ca sn lng buffer v sp xp m ca bn sao chp thm no descriptors-nh l
mt vt cht descriptor-rng bn c th c.

Cng vic ca bn trong minidriver l in trong c cu descriptor nh nu bn l


mt USB-HID thit b tiu chun. V d:

case IOCTL_HID_GET_DEVICE_DESCRIPTOR:

#define p ((PHID_DESCRIPTOR) buffer)

if (cbout < sizeof(HID_DESCRIPTOR))

status = STATUS_BUFFER_TOO_SMALL;

break;

RtlZeroMemory(p, sizeof(HID_DESCRIPTOR));

p->bLength = sizeof(HID_DESCRIPTOR);

p->bDescriptorType = HID_HID_DESCRIPTOR_TYPE;

p->bcdHID = HID_REVISION;

p->bCountry = 0;

p->bNumDescriptors = 1;

p->DescriptorList[0].bReportType = HID_REPORT_DESCRIPTOR_TYPE;

p->DescriptorList[0].wReportLength = sizeof(ReportDescriptor);

339/369
#undef p

info = sizeof(HID_DESCRIPTOR);

break;

Cc ch kha cnh ca m ny l khng c c t mt trong cng mt iu khin


tip theo l chiu di bn ch nh cho cc wReportLength thnh vin ca n
DescriptorList mc m bn cung cp. Gi tr ny nn l chiu di no thc s hay
dummy bo co descriptor bn s cung cp, p ng yu cu
IOCTL_HID_GET_REPORT_DESCRIPTOR.

Ch thch:

HIDCLASS gi mt yu cu IOCTL_HID_GET_REPORT_DESCRIPTOR l mt
phn ca cc ch bin ca IRP_MN_START_DEVICE yu cu v conceivably, vo
nhng thi gian khc, c c mt USB-HID tiu chun bo co descriptor.
UserBuffer cc lnh vc ca IRP im n nh l mt buffer ln nh bn ch nh s l
cn thit tr li ca bn trong mt IOCTL_HID_GET_DEVICE_DESCRIPTOR yu
cu.

Gi s bn c mt d liu tnh khu vc c tn ReportDescriptor c cha mt bo co


descriptor nh dng chun. Bn c th x l yu cu ny theo cch ny:

case IOCTL_HID_GET_REPORT_DESCRIPTOR:

if (cbout < sizeof(ReportDescriptor))

status = STATUS_BUFFER_TOO_SMALL;

break;

RtlCopyMemory(buffer, ReportDescriptor,

sizeof(ReportDescriptor));

340/369
info = sizeof(ReportDescriptor);

break;

Bc u tin ca bn trong vic xy dng cc bo co descriptor c thit k b


tr cc bo co. USB HID c im k thut cho cc thit b lm cho n c v rng bn
ang kh nhiu thit k min ph cho bt k loi bo co bn mun, vi cc Windows s
thc hin rng con s no ch ra nhng g lm vi cc d liu kt qu. Trong kinh
nghim ca ti, tuy nhin, bn tht s khng c t do. Mt trong nhng la chn no
khi bn tit kim trong cng vic ca bn HID Cng c l to ra mt C-ngn ng tiu
tp tin, nh th ny mt (tng ng vi cc descriptor hin th trong Hnh 13-3):

char ReportDescriptor[64] = {

0x05, 0x05, // USAGE_PAGE (Gaming Controls)

0x09, 0x03, // USAGE (Gun Device )

0xa1, 0x01, // COLLECTION (Application)

0xa1, 0x02, // COLLECTION (Logical)

0x85, 0x01, // REPORT_ID (1)

0x05, 0x09, // USAGE_PAGE (Button)

0x09, 0x01, // USAGE (Button 1)

0x15, 0x00, // LOGICAL_MINIMUM (0)

0x25, 0x01, // LOGICAL_MAXIMUM (1)

0x75, 0x01, // REPORT_SIZE (1)

0x95, 0x01, // REPORT_COUNT (1)

0x81, 0x02, // INPUT (Data,Var,Abs)

0x75, 0x07, // REPORT_SIZE (7)

0x81, 0x03, // INPUT (Cnst,Var,Abs)

341/369
0xc0, // END_COLLECTION

0xa1, 0x02, // COLLECTION (Logical)

0x85, 0x02, // REPORT_ID (2)

0x05, 0x01, // USAGE_PAGE (Generic Desktop)

0x09, 0x30, // USAGE (X)

0x25, 0xff, // LOGICAL_MAXIMUM (-1)

0x75, 0x20, // REPORT_SIZE (32)

0xb1, 0x02, // FEATURE (Data,Var,Abs)

0xc0, // END_COLLECTION

0xa1, 0x02, // COLLECTION (Logical)

0x85, 0x03, // REPORT_ID (3)

0x05, 0x09, // USAGE_PAGE (Button)

0x09, 0x01, // USAGE (Button 1)

0x25, 0x01, // LOGICAL_MAXIMUM (1)

0x75, 0x01, // REPORT_SIZE (1)

0xb1, 0x02, // FEATURE (Data,Var,Abs)

0x75, 0x07, // REPORT_SIZE (7)

0xb1, 0x03, // FEATURE (Cnst,Var,Abs)

0xc0, // END_COLLECTION

0xc0 // END_COLLECTION

};

Bn c th ch n gin ny bao gm cc tp tin tiu ca bn trong trnh iu khin


xc nh ReportDescriptor bn tr v t IOCTL_HID_GET_REPORT_DESCRIPTOR.

342/369
IOCTL_HID_READ_REPORT Workhorse c IOCTL_HID_READ_REPORT cc hot
ng ca mt HIDCLASS mini driver. HIDCLASS vn v yu cu ny
c c mt nguyn HID bo co. HIDCLASS s dng nguyn liu bo co
IRP_MJ_READ v IOCTL_HID_GET_INPUT_REPORT p ng yu cu pht hnh
cho n t cp cao hn cc thnh phn, bao gm c ngi s dng ch ng dng
m gi ReadFile, HidD_GetInputReport, IDirectInputDevice8: GetDeviceData, hoc
IDirectInputDevice8:: Thm d kin.

Mt minidriver c th l nhn vin ca bt k ca mt s chin lc cung cp cc


bo co: Nu in thoi ca bn l mt lp trnh I / O (Pio) loi in thoi gn b vi
truyn thng xe but nh phn ngoi vi Interconnect (PCI), c l bn c th thc hin
phn cng abstraction layer (HAL) chc nng cho cc cuc gi derive cu trc d liu
cho mt bo co. Bn s ngay lp tc sau hon thnh IOCTL_HID_READ_REPORT
yu cu.

Nu in thoi ca bn gn vi mt truyn thng ca cc tuyn xe but v s dng mt


phn cng gin on thng bo cho cc my ch lu tr d liu bo co khi c sn,
bn cn phi thc hin mt chng trnh, p ng yu cu vi cc bo co khi chng tr
nn sn c. Interlocked bng cch s dng mt danh sch cho php bn c v lu d
liu bo co trong mt gin on dch v thng thng (ISR). Cc chng trnh s yu
cu ca bn ISR xp hng chm l mt th tc gi (DPC), sau m c th c v
lu d liu bo co.

Nu in thoi ca bn l mt nonstandard thit b USB, c l bn c th gi i


mt Urb derive d liu t bn c th son mt cu trc bo co. Bn c th
piggyback cc Urb IOCTL_HID_READ_REPORT trn in thoi ca bn, nu yu cu
ca nguyn liu bo co, khng c bo co ln hn HIDCLASS l mong. Trong trng
hp ny, bn s presumably dispatch thng l phn b b nh cho Urb t nonpaged b
nh, ci t mt hon thnh thi quen, v chuyn IRP xung PnP stack vi cng USB
trn bus driver. Hon thnh thi quen ca bn s min ph trong Urb, reformat bo co
d liu v thit lp IoStatus.Information bng kch c ca reformatted bo co, v tr li
STATUS_SUCCESS cho php cc IRP hon thnh.

Trong vn cn nhng tnh hung khc, bn c th cn phi pend cc


IOCTL_HID_READ_REPORT yu cu trong khi bn thc hin mt hoc nhiu I / O
hot ng tm np d liu th t in thoi ca bn, sau m bn mong mun
reformat vo bo co gi. Vi thit k ny, bn c cc vn thng thng lin kt vi
b nh m c IOCTL_HID_READ_REPORT tr n cc yu cu trong mt cch an
ton-hy b v hy b vi bt chi nhnh IRPs bn to ra.

Khng c vn g chng trnh bn devise, driver ca bn s thc hin vic ny bng


cch in cc IRP UserBuffer buffer vi mt bo co. V d:

343/369
case IOCTL_HID_READ_REPORT:

if (cbout < <size of report>)

status = STATUS_BUFFER_TOO_SMALL;

break;

<obtain report data>

RtlCopyMemory(buffer, <report>, <size of report>);

info = <size of report>;

break;

Ghi nh rng nu bo co ca bn descriptor bao gm nhiu hn mt bo co, bo


co d liu bn quay tr li HIDCLASS bt u vi mt 1-byte bo co nh danh.
IOCTL_HID_WRITE_REPORT HIDCLASS vn IOCTL_HID_WRITE_REPORT
cc yu cu v dch v IRP_MJ_WRITE v IOCTL_HID_SET_OUTPUT_REPORT
yu cu cp t mt thnh phn cp cao hn, chng hn nh mt ngi s dng-p dng
ch m cc cuc gi WriteFile, HidD_SetOutputReport, hoc IDirectInputDevice8::
SendDeviceData.

Sn lng cc bo co thng c s dng thit lp ch s cc loi, chng hn nh


LEDs v hin th bng iu khin. Cng vic ca bn trong mt minidriver l truyn
ti d liu bo co cc sn lng in thoi hoc n m phng hot ng ca mt
thit b HID nhn c mt bo co nh vy c ngha l do mt s. Thit b USB thc
hin cc lp hc c th kim sot-ng lnh Set_Report_Request (hoc ngi no khc
m h xc nh mt gin on-out endpoint) cho sn lng nhn c bo co, nhng
kin trc ca bn c th gi cho mt cch tip cn khc nhau.

Khng ging nh cc hot ng kim sot ni b HIDCLASS,


IOCTL_HID_WRITE_REPORT s dng METHOD_BUFFERED. iu ny c ngha
l cc lnh vc AssociatedIrp.SystemBuffer ca IRP cha cc a ch ca ngi sn

344/369
xut d liu v Parameters.DeviceIoControl.OutputBufferLength rng cc lnh vc ca
IO_STACK_LOCATION cha chiu di ca n.

IOCTL_HID_GET_FEATURE v IOCTL_HID_SET_FEATURE

HIDCLASS cc vn IOCTL_HID_GET_FEATURE v IOCTL_HID_SET_FEA


TURE yu cu c hoc vit mt c gi l tnh nng bo co. Mt ng dng c th
kch hot cc yu cu bng cch gi in thoi HidD_GetFeature hay HidD_SetFeature,
tng ng.

Bn c th nhng tnh nng bo co trong vng mt bo co descriptor. Theo nhn


nh ca cc HID c im k thut, tnh nng hu ch cho cc bo co c nhn
c thng tin cu hnh v ci t hn l cho polling in thoi trn mt c s
thng xuyn. Vi mt USB-tiu chun thit b, driver s dng Get_Report_Request v
Set_Report_Request lp-lnh c th thc hin chc nng ny. Trong minidriver cho
mt s cc loi thit b HID, bn cn phi cung cp mt s loi analogue nu bo co
ca bn descriptor bao gm cc tnh nng bo co.

Nhng I / O kim sot (IOCTL) hot ng cng l mt cch Microsoft mun bn thc
hin cc out-of-band giao tip gia mt ng dng v mt HID minidriver. Ghi nh rng
HIDCLASS khng cho php bt c ai m mt ca hng x l cc thit b gc (x
l c th c m ra ch cp cao b su tp) v khng kim sot bt k hot ng
nonstandard rng n s xy ra nhn c. Resorting m khng sleazy phng
php, nh l mt iu m ti s khng ni bt c iu g, c tht s l khng c cch
no khc cho cc ng dng HIDCLASS minidriver v mt giao tip.

Cc "u ra" m cho yu cu ny l mt d ca cc cu trc sau y:

typedef struct _HID_XFER_PACKET {

PUCHAR reportBuffer;

ULONG reportBufferLen;

UCHAR reportId;

} HID_XFER_PACKET, *PHID_XFER_PACKET;

HIDCLASS s dng cng mt c cu cho c hai GET_FEATURE v SET_FEATURE


yu cu, v n t IRP-> UserBuffer tr n n trong c hai trng hp qu. Trong
thc t, cc ch c s khc bit gia hai yu cu l chiu di ca c cu (mt) l trong
InputBufferLength tham s cho SET_FEATURE v trong OutputBufferLength tham s
cho GET_FEATURE. (Bn s khng chm sc ngay c v s khc bit ny. K t

345/369
HIDCLASS l mt ch tin cy ht nhn-gi, c bit l khng c l do xc minh
di ca tham s ny c cu.)

X l cng vic ca bn khi mt trong nhng yu cu l decode reportId cc gi tr,


m designates mt trong nhng tnh nng h tr cc bo co trnh iu khin ca bn.
c mt GET_FEATURE yu cu, bn nn t ti a reportBufferLen byte ca d
liu trong reportBuffer buffer v hon tt cc IRP vi IoStatus.Information t thnh s
byte bn sao chp. c mt SET_FEATURE yu cu, bn nn trch reportBufferLen
byte ca d liu t reportBuffer m.

y skeleton x l nhng yu cu hai:

case IOCTL_HID_GET_FEATURE:

#define p ((PHID_XFER_PACKET) buffer)

switch (p->reportId)

case FEATURE_CODE_XX:

if (p->reportBufferLen < sizeof(FEATURE_REPORT_XX))

status = STATUS_BUFFER_TOO_SMALL;

break;

RtlCopyMemory(p->reportBuffer, FeatureReportXx,

sizeof(FEATURE_REPORT_XX));

info = sizeof(FEATURE_REPORT_XX);

break;

346/369
break;

#undef p

case IOCTL_HID_SET_FEATURE:

#define p ((PHID_XFER_PACKET) buffer)

switch (p->reportId)

case FEATURE_CODE_YY:

if (p->reportBufferLen > sizeof(FEATURE_REPORT_YY))

status = STATUS_INVALID_PARAMETER;

break;

RtlCopyMemory(FeatureReportYy, p->reportBuffer,

p->reportBufferLen);

break;

break;

#undef p

6.2.3. V d:

347/369
case IOCTL_GET_PHYSICAL_DESCRIPTOR:

if (cbout < sizeof(PhysicalDescriptor))

status = STATUS_BUFFER_TOO_SMALL;

break;

PUCHAR p =

(PUCHAR) MmGetSystemAddressForMdlSafe(Irp->MdlAddress);

if (!p)

status = STATUS_INSUFFICIENT_RESOURCES;

break;

RtlCopyMemory(p,

PhysicalDescriptor, sizeof(PhysicalDescriptor));

info = sizeof(PhysicalDescriptor);

break;

Lu rng IOCTL ny s dng METHOD_OUT_DIRECT thay v


METHOD_NEITHER.

Ngoi ra, gu trong tm tr b sau trong HID c im k thut: "vt l descriptors


l hon ton ty chn. H thm phc tp v cung cp rt t trong tr li cho hu
ht cc thit b. " IOCTL_HID_GET_STRING HIDCLASS gi mt

348/369
IOCTL_HID_GET_STRING, ly mt chui m t nhng nh sn xut, sn phm,
hoc ni tip ca mt s in thoi. Mt ngi s dng-p dng ch ny c th
kch hot IOCTL bng cch gi in thoi HidD_GetManufacturerString, HidD_Get
ProductString, hoc HidD_GetSerialNumberString. The strings tng ng vi ty chn
xc nh bi nhng dy in thoi descriptor tiu chun ca mt thit b USB. Mt tham
s n hot ng cho bit chui m bn nn tr li, v trong ngn ng. A skeleton
x l kim sot hot ng ny l nh sau:

case IOCTL_HID_GET_STRING:

#define p ((PUSHORT) \

stack->Parameters.DeviceIoControl.Type3InputBuffer)

USHORT istring = p[0];

LANGID langid = p[1];

#undef p

PWCHAR string = NULL;

switch (istring)

case HID_STRING_ID_IMANUFACTURER:

string = <manufacturer name>;

break;

case HID_STRING_ID_IPRODUCT:

string = <product name>;

break;

case HID_STRING_ID_ISERIALNUMBER:

string = <serial number>;

349/369
break;

if (!string)

status = STATUS_INVALID_PARAMETER;

break;

ULONG lstring = wcslen(string);

if (cbout < lstring * sizeof(WCHAR))

status = STATUS_INVALID_BUFFER_SIZE;

break;

RtlCopyMemory(buffer, string, lstring * sizeof(WCHAR));

info = lstring * sizeof(WCHAR);

if (cbout >= info + sizeof(WCHAR))

((PWCHAR) buffer)[lstring] = UNICODE_NULL;

info += sizeof(WCHAR);

break;

350/369
Mt s tin v cc im cht ny l cc m fragment:

Ging nh hu ht cc minidriver IOCTL yu cu ny, s dng mt


METHOD_NEITHER. Trong bi cnh ca DispatchInternalControl gi li trnh by
trc, buffer l sn phm m c y.

Cc s s-ri, nu c mt, nn c duy nht cho mi in thoi.

Cc minidriver nn khng thnh cng vi cc yu cu STATUS_INVALID_PARAM


ETER khng hp l nu mt chui ch mc xut hin v STATUS_INVALID_BUF
FER_SIZE nu c cung cp mt buffer nhng l qu nh gi ton b chui. Cc
minidriver tr li ton b chui hoc khng c g. N l mt appends null Terminator
chui nu sn lng buffer l ln.

The DDK khng ch nh, khng c g phi lm g nu c yu cu ngn ng khng


phi l mt trong nhng in thoi ca bn hay minidriver s xy ra h tr. Ti
s khng ngh vi cc yu cu STATUS_DEVICE_DATA_ERROR bt chc
nhng g thc s l mt thit b USB l v phi lm. Tuy nhin, nu khng c h tr
cc ngn ng l 0x0409 (Anh M), ti ngh tr li mt chui mc nh ca mt s
loi- thm ch c l l ngi u tin ngn ng ca bn trong danh sch cc ngn ng
c h tr bi v HIDCLASS-0x0409 lun lun s dng cho cc ngn ng id tham s
trong Windows XP v cc phin bn c ca h thng.

IOCTL_HID_GET_INDEXED_STRING HIDCLASS gi mt
IOCTL_HID_GET_INDEXED_STRING, ly mt chui c USB-tiu chun nh
danh mc cc ngn ng v c ch nh. Mt ngi s dng-ch c th kch hot
chng trnh ny IOCTL bng cch gi in thoi HidD_GetIndexedString. Bn x l
yu cu ny nhiu nh IOCTL_HID_GET_STRING ngoi tr cho hai im:

kim sot hot ng ny s dng mt s pha trn k l ca hai phng php buffering:

cc d liu u vo ch mc cha chui v cc ngn ng id l trong stack->


Parameters.DeviceIoControl.Type3InputBuffer (nh s l ng yu cu ca mt
METHOD_NEITHER), v l sn lng buffer m t bi cc danh sch b nh
descriptor (MDL) ti khch sn IRP-> MdlAddress, nh s l ng yu cu ca mt
METHOD_OUT_DIRECT. Cc chui ch mc trong thp th t 16-bit ca
Type3InputBuffer-USB l mt chui mc cc tiu chun thay v l mt v d nh
HID_STRING_ID_IMANUFACTURER. Mc ch ca yu cu ny l cho php cc
ng dng, ly cc chui gi tr tng ng vi chui Usages HID trong mt bo co.
Thit b USB c th lm cho ln n 255 trong chui gi tr c th truy cp bng cch
ny. Vi mt nonstandard USB hoc mt thit b USB khng in thoi, minidriver nhu
cu ca bn cung cp mt analogue nu cc bo co descriptor cha chui Usages.

351/369
IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST HIDCLASS gi mt
IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST sc mnh xung mt
thit b nhn ri. Vi mt thit b USB thc t, yu cu ny dovetails vi cc tnh nng
USB chn la tm ngng tho lun trong chng trc.

Cc u vo m cho METHOD_NEITHER yu cu ny l mt d ca cc cu trc sau


y:

typedef struct _HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO {

HID_SEND_IDLE_CALLBACK IdleCallback;

PVOID IdleContext;

} HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO,

*PHID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO;

where HID_SEND_IDLE_CALLBACK is declared as follows:

typedef void (*HID_IDLE_CALLBACK)(PVOID Context);

Lu rng cu trc ny l ging ht nhau trong b tr v ngha cho mt USB c s


dng vi chn la treo. Trong thc t, xy ra, nu in thoi ca bn phi l mt thit
b USB, bn c th ch cn chuyn IRP xung stack sau khi thay i chc nng m:

case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:

IoCopyCurrentIrpStackLocationToNext(Irp);

stack = IoGetNextIrpStackLocation(Irp);

stack->Parameters.DeviceIoControl.IoControlCode =

IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION;

return IoCallDriver(pdx->LowerDeviceObject, Irp);

Nu in thoi ca bn khng phi l mt thit b USB, tuy nhin, bn nn gi li ngay


HIDCLASS v hon tt cc IRP, nh c hin th y

352/369
case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:

PHID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO p =

(PHID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO)

stack->Parameters.DeviceIoControl.Type3InputBuffer;

(*p->IdleCallback)(p->IdleContext);

break;

HIDCLASS gi li cho rng n c th ngay lp tc sc mnh ca thit b xung.

353/369
Bi 22: THC HNH LP TRNH HID
Thc hnh vi cc chng trnh v d iu khin cho HID
Bi 1.

Xem xt file HIDCLASS.SYS v rt ra kinh nghim trong lp trnh HID.

Bi 2.

To cho mnh mt driver nh v HID.

354/369
Bi 23: THC HNH LP TRNH
DRIVER GIAO TIP CC CNG
Thc hnh mt s bi tp tng hp
Bi 1.

Lp trnh v cng COM

Bi 2.

Lp trnh cng LPT.

Bi 3.

Lp trnh USB

Bi 4.

Cc x l IRP

Bi 5.

Cc gi tin I/O

Bi 6.

iu khin cho thit b HID

355/369
TI LIU THAM KHO
Lp trnh h thng: Ti liu tham kho
Sch tham kho :

[1] O'Reilly, Practical C++ Programming. 2002.

[2] David J. Kruglinski, Programing microsoft Visual C++, 1998.

[3] Walter Oney, "Programming The Windows Driver Model, 2nd Edition (2003)".

[4] Jan Axelson, USB Complete

[5] Jan Axelson, Serial Port Complete

[6] Kernal Driver programming in Linux

[7] Nguyn Minh San, Cm nang Lp trnh h thng (bn dch). NXB Tng cc Thng
k.2001.

[8] Ng Din Tp, Lp trnh Ghp ni my tnh trong Windows. NXB Khoa hc v k
thut. 2001.

356/369
MC LC
Lp trnh h thng: Mc lc
Bi 1: TNG QUAN V LP TRNH H THNG 1

1.1 Khi nim v lp trnh h thng 1

1.2 Tng quan 1

1.3 Lch s 1

1.4 Cu trc tng quan lp trnh h thng 2

Bi 2: CNG C LP TRNH H THNG 2

2.1 Cc ngn ng lp trnh 2

2.2 Gii thiu v C++ 3

2.3 Gii thiu v Visual C++ 5

2.4 Giao bi tp ln nghin cu v C++ v Visual C++ 9

Bi 3: Thc hnh mt s bi tp c bn trn C++ 9

Bi 4: C BN V CU TRC V DRIVER 10

4.1 Tm lc lch s cc b iu khin thit b 10

4.2 Tng quan v cc H iu hnh 13

4.3 Cc kiu Driver 14

4.4 Tng quan v qun l v kim tra danh sch 18

Bi 5: Thc hnh mt s bi tp c bn trn VC++ 19

Bi 6: CC K THUT LP TRNH C BN 20

6.1 Mi trng lp trnh Kernel mode 20

357/369
6.2 X l li 21

6.3 Qun l b nh 33

6.4 X l chui 44

6.5 Mt s k thut lp trnh khc 44

Bi 7: Thc hnh mt s bi tp c bn trn VC++ 55

Bi 8: LP TRNH GIAO TIP QUA CNG LPT 56

8.1 Gii thiu cng LPT 56

8.2 Cu trc cng LPT 56

8.3 Lp trnh cho cng LPT 59

Bi 9: Thc hnh vi cc chng trnh giao tip qua cng LPT 60

Bi 10: Thc hnh vi cc chng trnh giao tip qua cng COM 60

10.1 Gii thiu cng COM 60

10.2 Cu trc cng COM 60

10.3 Lp trnh cho cng COM 63

Bi 11: Thc hnh vi cc chng trnh giao tip qua cng COM 64

Bi 12: VN NG B 64

12.1 Gii thiu v vn ng b 64

12.2 Mc yu cu Ngt 66

12.3 Kha xoay vng 69

12.4 Cc i tng Kernel Dispatcher 71

12.5 Mt s phng php ng b khc 82

Bi 13: Thc hnh lp trnh driver c bn 90

358/369
Bi 14: GI D LIU VO RA 90

14.1 Cc cu trc d liu 90

14.2 Hng i yu cu vo/ra 99

14.3 Hy b yu cu vo/ra 105

14.4 Tm lc cc kch bn x l 117

Bi 15: Thc hnh lp trnh driver cho x l IRP 128

Bi 16: C V GHI D LIU 128

16.1 Cu hnh thit b ca bn 128

16.2 a ch mt B m d liu 131

16.3 Cc cng v cc thanh ghi 134

16.4 Phc v ngt 139

16.5 Truy nhp b nh trc tip 150

Bi 17: IU KHIN VO/RA V HM IU KHIN PLUG AND PLAY 165

17.1 Hm DeviceIoControl API 165

17.2 iu khin IRP_MJ_DEVICE_CONTROL 168

17.3 Nhng thao tc bn trong iu khin vo/ra 169

Bi 18: Thc hnh lp trnh driver cho iu khin vo/ra 177

Bi 19: TRNH IU KHIN CHO USB 177

19.1 Gii thiu cng USB 177

19.2 Cu trc cng USB 185

19.3 Lp trnh cho cng USB 185

Bi 20: Thc hnh iu khin qua cng USB 185

359/369
Bi 21: TRNH IU KHIN CHO HID 185

21.1 Nhng Driver cho nhng thit b HID 185

21.2 Nhng miu t bo co v nhng bo co 186

21.3 Nhng iu khin nh HIDCLASS 190

Bi 22: Thc hnh lp trnh HID 206

Bi 23: Thc hnh lp trnh driver giao tip cc cng 206

Ti liu tham kho 207

360/369
Tham gia ng gp
Ti liu: LP TRNH H THNG
Bin tp bi: Khoa CNTT HSP KT Hng Yn
URL: http://voer.edu.vn/c/92c88426
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Khi nim v lp trnh h thng


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/a49cc356
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Tng quan v lp trnh h thng


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/e391eb05
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Lch s v lp trnh h thng


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/a30b5f62
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Cu trc tng quan lp trnh h thng


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/d6321b07
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Cc ngn ng lp trnh


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/aaff2f01
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Gii thiu v C++


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/6a337c50

361/369
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Gii thiu v Visual C++


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/fb4931be
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Thc hnh mt s bi tp c bn trn C++


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/47d3c10c
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Tm lc lch s cc b iu khin thit b


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/22e3a510
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Tng quan v cc H iu hnh (An Overview of the Operating Systems)


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/6ce1e258
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Cc kiu Driver


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/52902179
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Tng quan v qun l v kim tra danh sch


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/59ef89b3
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Thc hnh mt s bi tp c bn trn VC++


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/8f5e20fe
Giy php: http://creativecommons.org/licenses/by/3.0/

362/369
Module: Mi trng lp trnh kiu Kernel Mode
Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/e7a02045
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Trnh by li (Li x l)


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/74443955
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Qun l b nh (Memory Management )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/ed388986
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Trnh by chui (String Handling)


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/843cd3a3
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: K thut lp trnh hn hp (Miscellaneous Programming Techniques )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/b122a86e
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Thc hnh mt s bi tp c bn trn Visual C++


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/5282d97c
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Gii thiu cng LPT


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/c2bc02c8
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Cu trc cng LPT

363/369
Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/9677d96a
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Thc hnh vi cc chng trnh giao tip qua cng LPT
Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/085b2a8a
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Gii thiu cng COM


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/98901eae
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Cu trc cng COM


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/2a8a5ee0
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Thc hnh vi cc chng trnh giao tip qua cng COM
Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/3a6f15ba
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Vn ng b ha nguyn mu (An Archetypal Synchronization Problem )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/140bff64
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Mc yu cu Ngt (Interrupt Request Level )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/d0cd65bd
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Kha xoay vng (Spin Locks )


Cc tc gi: Khoa CNTT HSP KT Hng Yn

364/369
URL: http://www.voer.edu.vn/m/e6bcd0d2
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Cc i tng Kernel Dispatcher (Kernel Dispatcher Objects )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/be5dd762
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Mt s phng php ng b khc (Other Kernel-Mode Synchronization


Primitives )
Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/bfcc3fdc
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Thc hnh lp trnh driver c bn


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/d73d84fe
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Cc cu trc d liu (Data Structures )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/b116212a
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Hng i yu cu Vora (Queuing IO Requests)


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/4c2e2899
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Hy b yu cu vora (Cancelling IO Requests )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/822823e6
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Tm lc cc kch bn x l (SummaryEight IRP-Handling Scenarios)


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/82adc58e

365/369
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Thc hnh mt s bi lp trnh driver c bn


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/134ffac0
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Cu hnh thit b ca bn (Configuring Your Device )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/d8b0c61e
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: a ch mt B m d liu (Addressing a Data Buffer )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/03371bec
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Cc cng v cc thanh ghi (Ports and Registers )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/6e8847f9
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Phc v ngt (Servicing an Interrupt )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/75ea0faf
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Truy nhp b nh trc tip (Direct Memory Access )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/1ae10d10
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Hm DeviceIoControl API (The DeviceIoControl API)


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/108f5bf0
Giy php: http://creativecommons.org/licenses/by/3.0/

366/369
Module: iu khin IRP MJ DEVICE CONTROL
Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/53878970
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Nhng thao tc bn trong iu khin IO (Internal IO Control Operations)


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/4adbdc59
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Thc hnh lp trnh driver cho iu khin Vora


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/067f189c
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Gii thiu cng USB


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/2fe86ea1
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Thc hnh vi cc chng trnh v d iu khin qua cng USB


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/5c233f4c
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Nhng b iu khin cho thit b HID (Drivers for HID Devices )
Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/90dff5b9
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Nhng m t bo co v nhng bo co (Reports and Report Descriptors )


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/49843cc2
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Nhng iu khin nh HIDCLASS (HIDCLASS Minidrivers)

367/369
Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/8c4f582d
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Thc hnh vi cc chng trnh v d iu khin cho HID


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/ec342de2
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Thc hnh mt s bi tp tng hp


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/b915e5a2
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Lp trnh h thng: Ti liu tham kho


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/41acc5c3
Giy php: http://creativecommons.org/licenses/by/3.0/

Module: Lp trnh h thng: Mc lc


Cc tc gi: Khoa CNTT HSP KT Hng Yn
URL: http://www.voer.edu.vn/m/853c5ece
Giy php: http://creativecommons.org/licenses/by/3.0/

368/369
Chng trnh Th vin Hc liu M Vit Nam

Chng trnh Th vin Hc liu M Vit Nam (Vietnam Open Educational Resources
VOER) c h tr bi Qu Vit Nam. Mc tiu ca chng trnh l xy dng kho
Ti nguyn gio dc M min ph ca ngi Vit v cho ngi Vit, c ni dung phong
ph. Cc ni dung u tun th Giy php Creative Commons Attribution (CC-by) 4.0
do cc ni dung u c th c s dng, ti s dng v truy nhp min ph trc
ht trong trong mi trng ging dy, hc tp v nghin cu sau cho ton x hi.

Vi s h tr ca Qu Vit Nam, Th vin Hc liu M Vit Nam (VOER) tr thnh


mt cng thng tin chnh cho cc sinh vin v ging vin trong v ngoi Vit Nam. Mi
ngy c hng chc nghn lt truy cp VOER (www.voer.edu.vn) nghin cu, hc
tp v ti ti liu ging dy v. Vi hng chc nghn module kin thc t hng nghn
tc gi khc nhau ng gp, Th Vin Hc liu M Vit Nam l mt kho tng ti liu
khng l, ni dung phong ph phc v cho tt c cc nhu cu hc tp, nghin cu ca
c gi.

Ngun ti liu m phong ph c trn VOER c c l do s chia s t nguyn ca cc


tc gi trong v ngoi nc. Qu trnh chia s ti liu trn VOER tr ln d dng nh
m 1, 2, 3 nh vo sc mnh ca nn tng Hanoi Spring.

Hanoi Spring l mt nn tng cng ngh tin tin c thit k cho php cng chng d
dng chia s ti liu ging dy, hc tp cng nh ch ng pht trin chng trnh ging
dy da trn khi nim v hc liu m (OCW) v ti nguyn gio dc m (OER) . Khi
nim chia s tri thc c tnh cch mng c khi xng v pht trin tin phong
bi i hc MIT v i hc Rice Hoa K trong vng mt thp k qua. K t , phong
tro Ti nguyn Gio dc M pht trin nhanh chng, c UNESCO h tr v c
chp nhn nh mt chng trnh chnh thc nhiu nc trn th gii.

369/369

You might also like