Bagikan melalui


Mengakses Buffer Data di Driver WDF (KMDF atau UMDF)

Ketika driver Windows Driver Frameworks (WDF) menerima permintaan kontrol I/O baca, tulis, atau perangkat, objek permintaan berisi buffer input, buffer output, atau keduanya.

Buffer input berisi informasi yang dibutuhkan driver. Untuk permintaan tulis, informasi ini biasanya merupakan data yang harus dikirim driver fungsi ke perangkat. Untuk permintaan kontrol I/O perangkat, buffer input mungkin berisi informasi yang menunjukkan jenis operasi yang harus dilakukan driver.

Buffer output menerima informasi dari driver. Untuk permintaan baca, informasi ini biasanya merupakan data yang diterima driver fungsi dari perangkat. Untuk permintaan kontrol I/O perangkat, buffer output mungkin menerima status atau informasi lain yang ditentukan oleh kode kontrol I/O permintaan.

Teknik yang digunakan driver Anda untuk mengakses buffer data permintaan tergantung pada metode driver untuk mengakses buffer data untuk perangkat. Ada tiga metode akses:

  • I/O yang di-buffer. Manajer I/O membuat buffer perantara yang dibagikan dengan driver.
  • I/O langsung. Manajer I/O mengunci ruang buffer ke dalam memori fisik, lalu memberi driver akses langsung ke ruang buffer.
  • Baik di-buffer maupun I/O langsung. Manajer I/O memberi driver alamat virtual ruang buffer permintaan. Manajer I/O tidak memvalidasi ruang buffer permintaan, sehingga driver harus memverifikasi bahwa ruang buffer dapat diakses dan mengunci ruang buffer ke dalam memori fisik.

Driver Kernel-Mode Driver Framework (KMDF) dapat menggunakan salah satu dari tiga metode akses. Driver User-Mode Driver Framework (UMDF) dapat menggunakan I/O buffer atau langsung untuk permintaan baca, tulis, dan IOCTL, dan dapat mengonversi permintaan yang menentukan metode METHOD_NEITHER.

Menentukan Metode Akses Buffer

Driver KMDF

Untuk permintaan baca dan tulis, semua driver dalam tumpukan driver harus menggunakan metode yang sama untuk mengakses buffer perangkat, kecuali untuk driver tingkat tertinggi, yang dapat menggunakan metode "tidak keduanya", terlepas dari metode mana yang digunakan oleh driver yang lebih rendah.

Mulai versi 1.13, driver KMDF menentukan metode akses untuk semua permintaan baca dan tulis perangkat dengan memanggil WdfDeviceInitSetIoTypeEx untuk setiap perangkat. Misalnya, jika driver menentukan metode I/O yang di-buffer untuk salah satu perangkatnya, manajer I/O menggunakan metode I/O yang di-buffer saat mengirimkan permintaan baca dan tulis ke driver untuk perangkat tersebut.

Untuk permintaan kontrol I/O perangkat, kode kontrol I/O (IOCTL) berisi bit yang menentukan metode akses buffer. Akibatnya, driver KMDF tidak perlu mengambil tindakan apa pun untuk memilih metode buffering untuk IOCTL. Untuk informasi selengkapnya tentang IOCTL, lihat Menentukan Kode Kontrol I/O. Tidak seperti permintaan baca dan tulis, semua IOCTL perangkat tidak perlu menentukan metode akses yang sama.

Driver UMDF

Driver UMDF menentukan preferensi untuk metode akses yang digunakan kerangka kerja untuk permintaan baca dan tulis, serta permintaan kontrol I/O perangkat. Nilai yang disediakan driver UMDF hanya preferensi, dan tidak dijamin digunakan oleh kerangka kerja. Untuk informasi selengkapnya, lihat Mengelola Metode Akses Buffer di Driver UMDF.

Driver UMDF menentukan metode akses untuk semua permintaan baca, tulis, dan IOCTL perangkat dengan memanggil WdfDeviceInitSetIoTypeEx untuk setiap perangkat. Misalnya, jika driver menentukan metode I/O yang di-buffer untuk salah satu perangkatnya, kerangka kerja menggunakan metode I/O yang di-buffer saat mengirimkan permintaan baca, tulis, dan IOCTL ke driver untuk perangkat tersebut.

Perhatikan perbedaan teknik akses buffer untuk IOCTL antara KMDF dan UMDF. Driver KMDF tidak menentukan metode akses buffer untuk IOCTL, sedangkan driver UMDF menentukan metode akses buffer untuk IOCTL.

Jika driver WDF menjelaskan buffer permintaan I/O dengan menggunakan teknik yang salah untuk metode I/O yang digunakan target I/O, kerangka kerja akan mengoreksi deskripsi buffer. Misalnya, jika driver menggunakan MDL untuk menjelaskan buffer yang diteruskan ke WdfIoTargetSendReadSynchronously, dan jika target I/O menggunakan I/O buffer (yang mengharuskan buffer ditentukan menggunakan alamat virtual alih-alih MDL), kerangka kerja mengonversi deskripsi buffer dari MDL ke alamat virtual dan panjang. Namun, lebih efisien jika driver Anda menentukan buffer dalam format yang benar.

Untuk informasi tentang objek memori kerangka kerja, daftar tampilan, MDL, dan buffer lokal, lihat Menggunakan Buffer Memori.

Untuk informasi tentang kapan buffer memori dihapus, lihat Siklus Hidup Buffer Memori.

Mengakses Buffer Data untuk I/O Buffered

Jika driver Anda menggunakan I/O buffer, perilakunya berubah tergantung pada jenis permintaan data dan apakah itu menggunakan KMDF atau UMDF.

Driver KMDF

Ketika driver KMDF menggunakan I/O buffer, manajer I/O membuat satu buffer perantara yang dapat diakses driver untuk setiap jenis permintaan. Inilah yang terjadi:

  • Menulis permintaan. Manajer I/O mentransfer info input dari buffer input aplikasi panggilan sebelum memanggil tumpukan driver. Kemudian, driver KMDF membaca info input dari buffer perantara dan menulisnya ke perangkat.
  • Membaca permintaan. Driver KMDF membaca info dari perangkat dan menyimpannya di buffer perantara. Kemudian, manajer I/O menyalin data output dari buffer perantara ke buffer output aplikasi.
  • Permintaan kontrol I/O perangkat. Driver KMDF membaca atau menulis data untuk permintaan tersebut ke atau dari buffer perantara.

Driver UMDF

Ketika driver UMDF menggunakan I/O buffer, proses host driver membuat satu atau dua buffer perantara, tergantung pada jenis permintaan. Inilah yang terjadi:

  • Menulis permintaan. Kerangka kerja membuat satu buffer, mentransfer info input dari buffer input aplikasi panggilan, lalu memanggil tumpukan driver. Driver UMDF membaca info input dari buffer perantara dan menulisnya ke perangkat.
  • Membaca permintaan. Driver UMDF membaca info dari perangkat dan menyimpannya dalam buffer yang dibuat kerangka kerja. Proses host driver menyalin data output dari buffer perantara ke buffer output aplikasi.
  • Permintaan kontrol I/O perangkat. Kerangka kerja membuat dua buffer yang sesuai dengan buffer input dan output IOCTL yang dapat diakses driver. Kerangka kerja menyalin info input dari IOCTL ke dalam buffer perantara baru dan membuatnya tersedia untuk driver. Kerangka kerja tidak menyalin konten buffer output, sehingga driver tidak boleh mencoba membacanya (jika tidak, akan akhirnya membaca data sampah). Setiap data yang ditulis driver ke buffer output disalin kembali ke buffer IOCTL asli dan dikembalikan ke aplikasi setelah berhasil menyelesaikan permintaan I/O. Perhatikan bahwa setiap data yang ditulis driver ke buffer input dibuang dan tidak dikembalikan ke aplikasi panggilan.

Untuk mengambil handel ke objek memori kerangka kerja yang mewakili buffer, driver KMDF dan UMDF memanggil WdfRequestRetrieveInputMemory atau WdfRequestRetrieveOutputMemory, tergantung pada apakah ini adalah permintaan baca atau tulis. Driver kemudian dapat mengambil pointer ke buffer dengan memanggil WdfMemoryGetBuffer. Untuk membaca dan menulis buffer, driver memanggil WdfMemoryCopyFromBuffer atau WdfMemoryCopyToBuffer.

Untuk mengambil alamat virtual dan panjang buffer, driver memanggil WdfRequestRetrieveInputBuffer atau WdfRequestRetrieveOutputBuffer.

Untuk mengalokasikan dan membangun daftar deskriptor memori (MDL) untuk buffer, driver KMDF memanggil WdfRequestRetrieveInputWdmMdl atau WdfRequestRetrieveOutputWdmMdl.

Mengakses Buffer Data untuk I/O Langsung

Driver KMDF

Jika driver Anda menggunakan I/O langsung, manajer I/O memverifikasi aksesibilitas ruang buffer yang berasal dari permintaan I/O (biasanya aplikasi mode pengguna) yang ditentukan, mengunci ruang buffer ke dalam memori fisik, dan kemudian memberi driver akses langsung ke ruang buffer.

Driver UMDF

Jika driver Anda telah menentukan preferensi untuk I/O langsung, dan semua persyaratan UMDF untuk I/O langsung telah terpenuhi (lihat Mengelola Metode Akses Buffer di Driver UMDF), kerangka kerja memetakan buffer memori yang diterimanya dari manajer I/O langsung ke ruang alamat proses host driver, dan dengan demikian memberi driver akses langsung ke ruang buffer.

Untuk mengambil handel ke objek memori kerangka kerja yang mewakili ruang buffer, driver memanggil WdfRequestRetrieveInputMemory atau WdfRequestRetrieveOutputMemory. Driver kemudian dapat mengambil pointer ke buffer dengan memanggil WdfMemoryGetBuffer. Untuk membaca dan menulis buffer, driver memanggil WdfMemoryCopyFromBuffer atau WdfMemoryCopyToBuffer.

Untuk mengambil alamat virtual dan panjang ruang buffer, driver memanggil WdfRequestRetrieveInputBuffer atau WdfRequestRetrieveOutputBuffer.

Jika driver perangkat menggunakan I/O langsung, manajer I/O menjelaskan buffer dengan menggunakan MDL. Untuk mengambil pointer ke MDL buffer, driver KMDF memanggil WdfRequestRetrieveInputWdmMdl atau WdfRequestRetrieveOutputWdmMdl. Driver UMDF tidak dapat mengakses MDL.

Mengakses Buffer Data untuk I/O Buffered maupun Direct

Driver KMDF

Jika driver Anda menggunakan metode akses buffer yang dikenal sebagai metode I/O yang tidak di-buffer atau I/O langsung (atau, metode "tidak keduanya", singkatnya), manajer I/O hanya menyediakan driver dengan alamat virtual yang berasal dari permintaan I/O yang ditentukan untuk ruang buffer permintaan. Manajer I/O tidak memvalidasi ruang buffer permintaan I/O, sehingga driver harus memverifikasi bahwa ruang buffer dapat diakses dan mengunci ruang buffer ke dalam memori fisik.

Alamat virtual yang disediakan manajer I/O hanya dapat diakses dalam konteks proses penangkal permintaan I/O. Hanya driver tingkat tertinggi dalam tumpukan driver yang dijamin akan dijalankan dalam konteks proses pencetus.

Untuk mendapatkan akses ke ruang buffer permintaan I/O, driver tingkat tertinggi harus menyediakan fungsi panggilan balik EvtIoInCallerContext . Kerangka kerja memanggil fungsi panggilan balik ini setiap kali menerima permintaan I/O untuk driver.

Jika metode akses buffer permintaan adalah "tidak keduanya," driver KMDF harus melakukan hal berikut untuk setiap buffer:

  1. Panggil WdfRequestRetrieveUnsafeUserInputBuffer atau WdfRequestRetrieveUnsafeUserOutputBuffer untuk mendapatkan alamat virtual buffer.

  2. Panggil WdfRequestProbeAndLockUserBufferForRead atau WdfRequestProbeAndLockUserBufferForWrite untuk memeriksa dan mengunci buffer dan untuk mendapatkan handel ke objek memori kerangka kerja untuk buffer.

  3. Simpan handel objek memori di ruang konteks permintaan.

  4. Panggil WdfDeviceEnqueueRequest, yang mengembalikan permintaan ke kerangka kerja.

Kerangka kerja kemudian menambahkan permintaan ke salah satu antrean I/O driver. Jika driver telah menyediakan penangan permintaan, kerangka kerja pada akhirnya akan memanggil penangan permintaan yang sesuai.

Handler permintaan dapat mengambil handel objek memori permintaan dari ruang konteks permintaan. Driver dapat meneruskan handel ke WdfMemoryGetBuffer untuk mendapatkan alamat buffer.

Terkadang, driver tingkat tertinggi harus menggunakan langkah-langkah sebelumnya untuk mengakses buffer mode pengguna, bahkan jika driver tidak menggunakan metode akses "tidak keduanya". Misalnya, driver menggunakan I/O yang di-buffer. Kode kontrol I/O yang menggunakan metode akses buffer mungkin melewati struktur yang berisi penunjuk tersemat ke buffer mode pengguna. Dalam kasus seperti itu, driver harus menyediakan fungsi panggilan balik EvtIoInCallerContext yang mengekstrak pointer dari struktur dan kemudian menggunakan langkah-langkah sebelumnya 2 hingga 4.

Driver UMDF

UMDF tidak mendukung buffer atau buffer tipe I/O langsung, sehingga driver UMDF tidak perlu menangani jenis buffer ini secara langsung.

Namun, jika kerangka kerja menerima buffer tersebut untuk dibaca atau ditulis dari manajer I/O, itu membuatnya tersedia untuk driver UMDF sebagai I/O buffer atau I/O langsung, tergantung pada metode akses yang dipilih oleh driver. Jika kerangka kerja menerima IOCTL yang menentukan metode buffer "tidak keduanya", secara opsional dapat mengonversi metode akses buffer permintaan IOCTL menjadi I/O buffer atau I/O langsung berdasarkan keberadaan arahan INF. Lihat Mengelola Metode Akses Buffer di Driver UMDF untuk informasi selengkapnya.