Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Driver fisik tingkat terendah memiliki rutinitas standar tertentu yang tidak diperlukan driver tingkat yang lebih tinggi. Set rutinitas standar untuk driver tingkat terendah juga bervariasi sesuai dengan kriteria berikut:
Sifat perangkat yang dikontrol setiap driver
Apakah driver mengatur objek perangkatnya untuk I/O langsung atau buffer
Desain driver individu
Untuk menjelaskan peran dari rutinitas driver standar, gambar berikut menunjukkan jalur yang dapat dilalui oleh IRP contoh saat diproses oleh driver perangkat penyimpanan masal tingkat terendah. Driver dalam gambar memiliki karakteristik berikut:
Perangkat menghasilkan gangguan di akhir setiap operasi I/O, sehingga driver ini memiliki rutinitas ISR dan DpcForIsr .
Driver memiliki rutinitas StartIo , daripada menyiapkan antrean internal untuk RUN dan mengelola antreannya sendiri.
Driver menggunakan DMA sistem, sehingga mengatur Bendera objek perangkatnya untuk I/O langsung, dan memiliki rutinitas AdapterControl .
Seperti yang ditunjukkan oleh gambar ini, manajer I/O membuat IRP dan mengirimkannya ke rutinitas pengiriman driver untuk kode fungsi utama yang diberikan. Dengan asumsi kode fungsi IRP_MJ_READ atau IRP_MJ_WRITE, rutinitas pengirimannya adalah DDDispatchReadWrite.
Memanggil IoGetCurrentIrpStackLocation
Setiap rutin driver yang memerlukan parameter IRP harus memanggil IoGetCurrentIrpStackLocation agar memperoleh lokasi tumpukan I/O driver. Rutinitas tersebut termasuk rutinitas pengiriman yang menangani lebih dari satu kode fungsi I/O utama (IRP_MJ_*XXX), menangani fungsi yang mendukung fungsi minor (IRP_MN_XXX), atau menangani permintaan kontrol I/O perangkat (*IRP_MJ_DEVICE_CONTROL dan/atau IRP_MJ_INTERNAL_DEVICE_CONTROL), bersama dengan setiap rutinitas driver lainnya yang memproses IRP.
Lokasi tumpukan I/O driver ini adalah yang terendah, dengan jumlah lokasi tumpukan I/O driver tingkat yang lebih tinggi yang ditampilkan berbayang. Untuk kesederhanaan, panggilan ke rutinitas IoGetCurrentIrpStackLocation dari rutinitas DispatchReadWrite, StartIo, AdapterControl, dan DpcForIsr tidak ditampilkan pada gambar sebelumnya.
Memanggil IoMarkIrpPending dan IoStartPacket
Driver sampel tidak menyelesaikan IRP dalam rutinitas pengirimannya, tetapi sebaliknya memproses IRP dalam rutinitas StartIo-nya . Sebelum dapat melakukannya, rutin pengiriman memanggil IoMarkIrpPending untuk menunjukkan bahwa IRP belum diselesaikan. Kemudian memanggil IoStartPacket untuk mengantrekan IRP untuk diproses lebih lanjut oleh rutinitas StartIo driver. Rutinitas pengiriman juga mengembalikan nilai NTSTATUS STATUS_PENDING.
Gambar berikut mengilustrasikan panggilan ke IoStartPacket.
Jika driver sibuk memproses IRP lain pada perangkat, IoStartPacket menyisipkan IRP ke dalam antrean perangkat yang terkait dengan objek perangkat. Pengemudi dapat secara opsional menyediakan nilai Kunci sebagai parameter ke IoStartPacket untuk memberlakukan urutan yang ditentukan pengemudi pada IRP dalam antrian perangkat.
Jika driver tidak sibuk dan antrean perangkat kosong, manajer I/O segera memanggil rutin StartIo tersebut, mengoper IRP input.
Untuk perangkat penyimpanan massal, driver tingkat terendah tidak perlu menyediakan rutinitas Batal saat memanggil IoStartPacket karena dua alasan:
Sistem file yang berlapis di atas driver seperti itu biasanya menangani pembatalan permintaan I/O file.
Driver perangkat penyimpanan massal memproses IRP dengan cepat.
Biasanya, driver tingkat tertinggi dalam rantai driver berlapis menangani pembatalan IRP.
Memanggil AllocateAdapterChannel dan MapTransfer
Dengan asumsi rutinitas StartIo , yang ditunjukkan pada gambar yang mengilustrasikan jalur IRP melalui rutinitas driver tingkat terendah, menentukan bahwa permintaan transfer dapat dilakukan oleh satu operasi DMA, rutinitas StartIo memanggil AllocateAdapterChannel dengan titik masuk rutinitas AdapterControl driver dan IRP.
Ketika pengontrol DMA sistem tersedia, manajer I/O memanggil rutin AdapterControl driver untuk menyiapkan operasi transfer. Rutinitas AdapterControl memanggil MapTransfer untuk menyiapkan pengontrol DMA sistem. Kemudian driver mengatur perangkatnya untuk menjalankan operasi DMA lalu kembali. (Untuk informasi selengkapnya tentang menggunakan objek DMA dan adaptor, lihat Teknik Input/Output.)
Memanggil IoRequestDpc dari ISR Driver
Ketika perangkat memberikan sinyal untuk menunjukkan bahwa operasi transfernya telah selesai, ISR milik driver menghentikan perangkat dari menghasilkan interupsi dan memanggil IoRequestDpc, seperti yang ditunjukkan pada gambar yang mengilustrasikan jalur IRP melalui rutinitas driver tingkat terendah.
Panggilan ini mengantrekan rutinitas DpcForIsr driver untuk menyelesaikan sebanyak mungkin operasi transfer pada prioritas perangkat keras yang lebih rendah (IRQL).
Memanggil IoStartNextPacket dan IoCompleteRequest
Ketika rutinitas DpcForIsr telah selesai memproses transfer, ia memanggil IoStartNextPacket segera sehingga rutinitas StartIo driver akan dipanggil dengan IRP berikutnya dalam antrean perangkat, jika ada yang diantrekan. Rutinitas DpcForIsr juga mengatur blok status I/O IRP yang baru saja selesai dan kemudian memanggil IoCompleteRequest untuk IRP.
Gambar berikut mengilustrasikan panggilan driver ini ke IoStartNextPacket dan IoCompleteRequest.
Driver harus memanggil IoStartNextPacket atau IoStartNextPacketByKey untuk memulai operasi I/O berikutnya yang diminta sesegera mungkin, sebaiknya sebelum mereka memanggil IoCompleteRequest.
Jika ada IRP yang diantrekan untuk perangkat, IoStartNextPacket memanggil KeRemoveDeviceQueue untuk menghapus IRP berikutnya dari antrean. Manajer I/O kemudian memanggil rutinitas StartIo driver, melewati IRP yang diantrekan. Jika tidak ada IRP yang saat ini berada dalam antrean perangkat, IoStartNextPacket sekadar mengembalikan kepada pemanggil.
Mengatur Blok Status I/O dalam IRP
Setiap driver tingkat terendah harus mengatur blok status I/O IRP sebelum memanggil IoCompleteRequest. (Pada gambar sebelumnya, area berbayang kedua menunjukkan blok status.) Blok status I/O menyediakan informasi kepada driver tingkat yang lebih tinggi dan, pada akhirnya, kepada pengaju asli operasi I/O. Driver tingkat yang lebih tinggi yang berlapis di atas driver pada gambar sebelumnya mungkin telah menyiapkan rutinitas IoCompletion yang membaca blok status I/O yang ditetapkan oleh driver ini. Driver tingkat yang lebih tinggi biasanya tidak memodifikasi blok status I/O dalam IRP yang telah diselesaikan oleh driver perangkat, kecuali driver tingkat yang lebih tinggi mencoba kembali IRP, dalam hal ini menginisialisasi ulang blok status I/O.
Setiap driver tingkat lebih tinggi yang menyelesaikan IRP tanpa mengirimkannya ke driver bawah berikutnya juga harus mengatur blok status I/O di IRP tersebut sebelum memanggil IoCompleteRequest. Untuk mendapatkan throughput I/O yang baik secara keseluruhan, driver tingkat tinggi harus memeriksa parameter pada lokasi tumpukan I/Onya sendiri untuk setiap IRP dan, jika parameter tidak valid, harus mengatur blok status I/O dan menyelesaikan permintaan itu sendiri. Jika memungkinkan, driver harus menghindari meneruskan permintaan yang tidak valid ke driver di bawahnya dalam rantai.
Dengan asumsi operasi transfer pada gambar sebelumnya berhasil, rutinitas DpcForIsr , yang ditunjukkan pada gambar yang mengilustrasikan jalur IRP melalui rutinitas driver tingkat terendah, menetapkan STATUS_SUCCESS dalam Status dan jumlah byte yang ditransfer dalam Informasi untuk blok status I/O IRP.
Banyak dari rutinitas driver standar juga mengembalikan nilai jenis NTSTATUS. Untuk informasi selengkapnya tentang konstanta NTSTATUS seperti STATUS_SUCCESS, lihat Kesalahan Pengelogan.