Bagikan melalui


Mengelola Antrean Perangkat

Manajer I/O biasanya (kecuali untuk FSD) membuat objek antrean perangkat terkait ketika driver memanggil IoCreateDevice. Ini juga menyediakan IoStartPacket dan IoStartNextPacket, yang dapat dipanggil driver supaya manajer I/O memasukkan IRP ke dalam antrean perangkat terkait atau memanggil rutinitas StartIo mereka.

Akibatnya, jarang diperlukan (atau sangat berguna) bagi driver untuk menyiapkan objek antrean perangkatnya sendiri untuk IRP. Kemungkinan kandidat adalah driver, seperti driver port SCSI, yang harus mengoordinasikan IRP masuk dari beberapa driver kelas yang terintegrasi erat untuk perangkat heterogen yang dikelola melalui satu pengontrol atau adaptor bus.

Dengan kata lain, driver untuk pengendali array disk lebih mungkin menggunakan objek pengendali yang dibuat oleh driver daripada mengatur objek antrean perangkat tambahan, sementara driver untuk adaptor bus tambahan dan kelompok driver kelas memiliki kemungkinan sedikit lebih tinggi untuk menggunakan antrean perangkat tambahan.

Menggunakan Antrean Perangkat Tambahan dengan StartIo Routine

Dengan memanggil IoStartPacket dan IoStartNextPacket, Dispatch driver dan DpcForIsr tinitas (atau CustomDpc) menyinkronkan panggilan ke rutinitas StartIo menggunakan antrean perangkat yang dibuat manajer I/O saat driver membuat objek perangkat. Untuk driver port dengan rutinitas StartIo, IoStartPacket dan IoStartNextPacket menyisipkan dan menghapus IRP dalam antrean perangkat dari pengontrol/adaptor perangkat bersama untuk driver port. Jika driver port juga menyiapkan antrean perangkat tambahan untuk menahan permintaan yang masuk dari driver kelas tingkat tinggi yang berhubungan erat, ia harus "menyortir" IRP masuk ke dalam antrean perangkat tambahannya, biasanya dalam rutinitas StartIo-nya.

Driver port harus menentukan antrean perangkat tambahan mana yang dimiliki setiap IRP sebelum mencoba memasukkan IRP tersebut ke dalam antrean yang sesuai. Penunjuk ke objek perangkat target diteruskan bersama IRP ke rutinitas dispatch driver. Driver harus menyimpan pointer untuk digunakan dalam "mengurutkan" IRP yang masuk. Perhatikan bahwa penunjuk objek perangkat yang diteruskan ke rutinitas StartIo adalah objek perangkat driver sendiri, yang mewakili pengontrol/adaptor perangkat, sehingga tidak dapat digunakan untuk tujuan ini.

Setelah mengantrekan IRP apa pun yang ada, driver memprogram pengontrol/adaptor yang digunakan bersama untuk melaksanakan permintaan. Dengan demikian, driver port dapat memproses permintaan masuk untuk semua perangkat berdasarkan urutan kedatangan sampai ada panggilan ke KeInsertDeviceQueue yang menempatkan IRP ke dalam antrean perangkat driver kelas tertentu.

Dengan menggunakan antrean perangkatnya sendiri untuk semua IRP yang akan diproses melalui rutin StartIo, driver port yang mendasar menserikan operasi melalui pengontrol/adaptor perangkat bersama (atau bus) ke semua perangkat yang terpasang. Dengan terkadang menyimpan IRP untuk setiap perangkat yang didukung dalam antrean perangkat terpisah, driver port ini menghambat pemrosesan IRP untuk perangkat yang sudah sibuk sambil meningkatkan throughput I/O untuk setiap perangkat lain yang melakukan I/O melalui perangkat keras bersama.

Menanggapi panggilan ke IoStartPacket dari rutinitas Dispatch driver port, manajer I/O segera memanggil rutinitas StartIo atau memasukkan IRP ke dalam antrean perangkat yang terkait dengan objek perangkat untuk pengontrol/adaptor bersama driver port.

Driver port harus mempertahankan informasi statusnya sendiri tentang setiap perangkat heterogen yang dilayaninya melalui pengontrol/adaptor perangkat bersama.

Ingat hal-hal berikut saat merancang driver kelas/port dengan antrean perangkat tambahan:

  • Driver tidak dapat dengan mudah mendapatkan penunjuk ke objek perangkat yang dibuat oleh driver lain yang berada di lapisannya, kecuali untuk objek perangkat yang berada di bagian atas stack perangkatnya.

    Secara desain, manajer I/O tidak menyediakan rutinitas dukungan untuk mendapatkan penunjuk seperti itu. Selain itu, urutan pemuatan driver membuatnya tidak dapat bagi driver level bawah untuk mendapatkan pointer untuk objek perangkat milik driver level atas yang belum dibuat ketika driver level bawah menambahkan perangkatnya.

    Meskipun IoGetAttachedDeviceReference mengembalikan pointer ke objek perangkat tingkat tertinggi dalam rangkaian driver, driver harus menggunakan pointer ini hanya untuk menunjuk target permintaan I/O ke rangkaiannya. Pengemudi tidak boleh mencoba membaca atau menulis obyek perangkat.

  • Driver tidak dapat menggunakan penunjuk ke objek perangkat yang dibuat oleh driver apa pun yang berlapis di atas dirinya sendiri, kecuali untuk mengirim permintaan ke bagian atas tumpukan perangkatnya sendiri.

    Tidak ada cara untuk menyinkronkan akses ke satu objek perangkat (dan ekstensi perangkatnya) antara dua driver dengan cara yang aman multiprosesor. Tidak ada driver yang dapat membuat asumsi tentang pemrosesan I/O apa yang saat ini dilakukan oleh driver lain.

Bahkan untuk driver kelas/port yang terkait erat, setiap driver kelas harus menggunakan penunjuk ke objek perangkat driver port hanya untuk mengirimkan IRP menggunakan IoCallDriver. Driver port dasar harus menjaga statusnya sendiri, mungkin di ekstensi perangkat driver port, terkait dengan permintaan-permintaan yang diprosesnya untuk perangkat driver kelas yang terhubung erat.

Mengelola Antrean Perangkat Tambahan Di Seluruh Rutinitas Driver

Setiap driver port yang mengantrekan Paket Permintaan I/O (IRP) dalam antrean tambahan perangkat untuk serangkaian driver kelas yang sangat terkait juga harus menangani situasi berikut secara efisien:

  1. Rutinitas Pengirimannya telah memasukkan IRP untuk perangkat tertentu ke dalam antrean perangkat yang dibuat oleh pengandar untuk perangkat tersebut.

  2. IRP untuk perangkat lain terus diterima, untuk diantrekan ke rutin StartIo driver dengan IoStartPacket, dan untuk diproses melalui pengontrol perangkat bersama.

  3. Pengontrol perangkat tidak menjadi menganggur, tetapi setiap IRP yang disimpan dalam antrean perangkat yang dibuat driver juga harus diantrekan ke StartIo driver rutin sesegera mungkin.

Akibatnya, rutinitas DpcForIsr driver port harus mencoba mentransfer IRP dari antrean perangkat internal driver untuk perangkat tertentu ke dalam antrean perangkat untuk adaptor/pengontrol bersama setiap kali driver port menyelesaikan IRP, sebagai berikut:

  1. DpcForIsr memanggil rutin IoStartNextPacket untuk memulai rutin StartIo dalam memproses IRP berikutnya yang diantrekan pada pengontrol perangkat bersama.

  2. DpcForIsr memanggil rutin KeRemoveDeviceQueue untuk menghapus antrean IRP berikutnya (jika ada) yang sedang disimpan dalam antrean perangkat internalnya untuk perangkat yang mana ia akan menyelesaikan IRP.

  3. Jika KeRemoveDeviceQueue mengembalikan penunjuk non-NULL, rutin DpcForIsr memanggil IoStartPacket dengan IRP yang baru saja dikeluarkan dari antrean agar dapat diantrekan ke pengontrol/adaptor perangkat bersama. Jika tidak, panggilan ke KeRemoveDeviceQueue hanya mengubah status objek antrean perangkat menjadi Tidak Sibuk, dan rutinitas DpcForIsr melewatkan panggilan ke IoStartPacket.

  4. Kemudian, rutin DpcForIsr menjalankan IoCompleteRequest dengan IRP masukan yang driver port baru saja menyelesaikan pemrosesan I/O, baik dengan mengatur blok status I/O sebagai kesalahan atau dengan memenuhi permintaan I/O.

Perhatikan bahwa urutan sebelumnya menyiratkan bahwa rutinitas DpcForIsr juga harus menentukan perangkat yang menyelesaikan IRP saat ini (input) untuk mengelola antrean internal IRP secara efisien.

Jika driver port mencoba menunggu hingga pengontrol/adaptor bersama menganggur sebelum menghapus IRP dari antrean perangkat tambahannya, driver mungkin menghambat perangkat yang permintaan I/O-nya tinggi sementara segera melayani setiap perangkat lain yang permintaan I/O saat ini lebih ringan.