Bagikan melalui


Contoh Sinkronisasi

Contoh berikut menggambarkan apa yang perlu dilakukan oleh minidriver mengenai sinkronisasi dan menyertakan contoh kapan sinkronisasi tidak boleh digunakan:

  • Contoh Satu: Minidriver Dengan ISR yang Berfungsi

    Jika sinkronisasi kelas streaming diaktifkan, semua titik entri minidriver dipanggil di IRQL yang dinaikkan, menggunakan KeSynchronizeExecution, yang berarti bahwa tingkat IRQ adaptor dan semua tingkat IRQ yang lebih rendah ditutupi saat minidriver menjalankan kodenya. Oleh karena itu, sangat penting bahwa minidriver hanya melakukan sejumlah kecil pekerjaan dalam mode ini.

    Minidriver tidak boleh menjalankan kode yang biasanya membutuhkan lebih dari 10 hingga 20 mikrodetik pada IRQL yang dinaikkan. Jika Anda menggunakan build debug stream.sys, kelas stream mencatat jumlah waktu yang dihabiskan pada IRQL yang ditingkatkan dan menegaskan jika driver menghabiskan terlalu banyak waktu di sana. Jika minidriver hanya perlu mengatur register DMA perangkat keras untuk permintaan, atau hanya perlu membaca port di ISR-nya, biasanya dapat diterima untuk melakukan semua pemrosesannya pada IRQL yang lebih tinggi.

    Jika minidriver perlu melakukan pemrosesan yang membutuhkan lebih dari beberapa mikro detik, seperti minidriver yang mentransfer data melalui PIO, minidriver harus menggunakan StreamClassCallAtNewPriority untuk menjadwalkan panggilan balik DISPATCH_LEVEL. Dalam panggilan balik, minidriver dapat memakan waktu hingga sekitar 1/2 hingga 1 milidetik untuk melakukan pemrosesannya. Satu hal yang perlu diingat ketika dalam mode ini adalah bahwa panggilan balik DISPATCH_LEVEL tidak disinkronkan dengan ISR.

    Kurangnya sinkronisasi ini tidak menjadi masalah jika perangkat keras tetap stabil ketika minidriver mengakses sumber daya (misalnya, port atau antrean) selama panggilan balik serta di ISR. Tetapi jika ketidakstabilan bisa menjadi masalah, minidriver harus menggunakan StreamClassCallAtNewPriority untuk menjadwalkan callback dengan prioritas TINGGI di mana callback pada DISPATCH_LEVEL mengakses sumber daya yang dibagikan dengan sumber daya yang digunakan oleh ISR.

    Perhatikan bahwa panggilan balik prioritas TINGGI setara dengan memanggil KeSynchronizeExecution. KeSynchronizeExecution memerlukan minidriver untuk mereferensikan beberapa parameter yang tidak dilakukan oleh StreamClassCallAtNewPriority, tetapi secara umum keduanya menghasilkan perilaku yang sama.

    Jika minidriver hanya sesekali perlu menjalankan kode yang membutuhkan waktu lebih dari 1/2 hingga 1 milidetik, atau sesekali harus memanggil layanan di PASSIVE_LEVEL (misalnya saat inisialisasi), maka mengatur StreamClassCallAtNewPriority ke prioritas RENDAH dapat digunakan untuk memperoleh utas pekerja PASSIVE_LEVEL. Perhatikan bahwa panggilan balik berprioritas rendah tidak disinkronkan dengan apa pun dan bahwa minidriver dapat menerima permintaan baru (dengan asumsi parameter ReadyForNextRequest NotificationType tertunda) atau panggilan ISR saat menjalankan panggilan balik prioritas rendah.

  • Contoh Dua: Minidriver Tanpa ISR

    Jika sinkronisasi kelas aliran diaktifkan, titik masuk minidriver semuanya dipanggil pada DISPATCH_LEVEL. Minidriver dapat melakukan pemrosesan hingga sekitar 1/2 hingga 1 milidetik tanpa perlu menyesuaikan prioritas. Jika minidriver hanya kadang-kadang perlu menjalankan kode yang membutuhkan waktu lebih dari 1/2 milidetik, atau kadang-kadang perlu memanggil layanan di PASSIVE_LEVEL (seperti pada waktu inisialisasi), maka StreamClassCallAtNewPriority dengan prioritas RENDAH dapat digunakan untuk memperoleh utas pekerja PASSIVE_LEVEL. Perhatikan bahwa panggilan balik berprioritas rendah tidak disinkronkan dengan apa pun dan minidriver dapat menerima permintaan baru (dengan asumsi parameter ReadyForNextRequest NotificationType tertunda) saat menjalankan panggilan balik berprioritas rendah.

  • Ketika Sinkronisasi Kelas StreamTidakSebaiknya Digunakan

    Berikut ini adalah contoh situasi di mana sinkronisasi kelas aliran tidak boleh digunakan. Ini termasuk:

    • Ketika driver sering (lebih dari sekitar 20 persen dari permintaan yang diterima minidriver) perlu melakukan pemrosesan yang membutuhkan waktu lebih dari 1 milidetik, atau perlu sering memanggil layanan PASSIVE_LEVEL, seperti layanan Microsoft DirectDraw. Saat menggunakan versi debug stream.sys, kelas streaming akan menegaskan kedua kasus ini dan menghentikan jika terdeteksi dengan sinkronisasi diaktifkan.

    • Ketika minidriver adalah filter tanpa perangkat keras terkait. Minidriver seperti itu harus berjalan pada PASSIVE_LEVEL karena tidak ada perangkat keras yang mendasar untuk disinkronkan dan minidriver biasanya melakukan banyak pemrosesan. Lebih mudah untuk melakukan sinkronisasi Anda sendiri dalam hal ini daripada membuang overhead menggunakan sinkronisasi kelas aliran. Jika perlu, gunakan mutex untuk melindungi antrean.

      Bug dalam kode sinkronisasi seringkali sulit ditemukan, dan di lingkungan tertentu (seperti sistem operasi berbasis NT yang berjalan pada sistem multiprosesor) bug mungkin muncul hanya setelah berjam-jam stres. Berdasarkan pengalaman dengan vendor, ini bukan jenis hal yang sebagian besar vendor memiliki kemampuan atau keinginan untuk debug. Hanya penulis driver yang terbiasa menulis driver perangkat WDM yang sepenuhnya asinkron yang harus mencoba melakukan sinkronisasi mereka sendiri.

    • Ketika minidriver adalah driver jenis bus-on-bus (misalnya, driver periferal USB atau 1394) yang tidak terlalu memperdulikan sinkronisasi perangkat keras sebenarnya, tetapi hanya mengarahkan permintaan ke lapisan berikutnya di PASSIVE_LEVEL dan seringkali menerima panggilan balik pada DISPATCH_LEVEL.