Bagikan melalui


Mengunci Kode atau Data yang Dapat Di-pageable

Driver mode kernel tertentu, seperti driver serial dan paralel, tidak harus residen memori kecuali perangkat yang mereka kelola terbuka. Namun, selama ada koneksi atau port aktif, beberapa bagian dari kode driver yang mengelola port tersebut harus residen untuk melayani perangkat. Ketika port atau koneksi tidak digunakan, kode driver tidak diperlukan. Sebaliknya, driver untuk disk yang berisi kode sistem, kode aplikasi, atau file paging sistem harus selalu menjadi memory-resident karena driver terus mentransfer data antara perangkatnya dan sistem.

Driver untuk perangkat yang digunakan secara sporadis (seperti modem) dapat membebaskan ruang sistem ketika perangkat yang dikelolanya tidak aktif. Jika Anda menempatkan di satu bagian kode yang harus merupakan residen untuk melayani perangkat aktif, dan jika driver Anda mengunci kode dalam memori saat perangkat sedang digunakan, bagian ini dapat ditetapkan sebagai dapat dipaginasi. Ketika perangkat driver dibuka, sistem operasi membawa bagian yang dapat di-pageable ke dalam memori dan driver menguncinya di sana sampai tidak lagi diperlukan.

Kode driver audio CD sistem menggunakan teknik ini. Kode untuk driver dikelompokkan ke dalam bagian yang dapat di-page sesuai dengan produsen perangkat CD. Merek tertentu mungkin tidak pernah ada pada sistem tertentu. Selain itu, bahkan jika CD-ROM ada pada sistem, itu mungkin jarang diakses, sehingga pengelompokan kode ke dalam bagian yang dapat di-pageable berdasarkan jenis CD memastikan bahwa kode untuk perangkat yang tidak ada di komputer tertentu tidak akan pernah dimuat. Namun, ketika perangkat diakses, sistem memuat kode untuk perangkat CD yang sesuai. Kemudian driver memanggil rutinitas MmLockPagableCodeSection , seperti yang dijelaskan di bawah ini, untuk mengunci kodenya ke dalam memori saat perangkatnya sedang digunakan.

Untuk mengisolasi kode yang dapat dipaginasi ke dalam bagian bernama, tandai dengan direktif kompilator berikut:

#pragma alloc_text(PAGE*Xxx, *RoutineName)

Nama bagian kode yang dapat dipaginasi harus dimulai dengan empat huruf "PAGE" dan dapat diikuti hingga empat karakter (dinyatakan di sini sebagai Xxx) untuk mengidentifikasi bagian secara unik. Empat huruf pertama dari nama bagian (yaitu, "PAGE") harus dikapitalisasi. RoutineName mengidentifikasi titik entri yang akan disertakan di bagian yang dapat dipakai.

Nama terpendek yang valid untuk bagian kode yang dapat di-pageable dalam file driver hanyalah PAGE. Misalnya, arahan pragma dalam contoh kode berikut mengidentifikasi RdrCreateConnection sebagai titik entri di bagian kode yang dapat dipaginasi bernama PAGE.

#ifdef  ALLOC_PRAGMA 
#pragma alloc_text(PAGE, RdrCreateConnection) 
#endif 

Untuk membuat kode driver yang dapat diperhitungkan dan dikunci dalam memori, driver memanggil MmLockPagableCodeSection, meneruskan alamat (biasanya titik masuk rutin driver) yang ada di bagian kode yang dapat dipaginasi. MmLockPagableCodeSection mengunci seluruh konten bagian yang berisi rutinitas yang dirujuk dalam panggilan. Dengan kata lain, panggilan ini membuat setiap rutinitas yang terkait dengan pengidentifikasiPAGE Xxx yang sama tinggal dan terkunci dalam memori.

MmLockPagableCodeSection mengembalikan handel yang akan digunakan saat membuka kunci bagian (dengan memanggil rutinitas MmUnlockPagableImageSection ) atau ketika driver harus mengunci bagian dari lokasi tambahan dalam kodenya.

Driver juga dapat memperlakukan data yang jarang digunakan sebagai dapat dipaginasi sehingga juga dapat di-paged out sampai perangkat yang didukungnya aktif. Misalnya, driver mixer sistem menggunakan data yang dapat di-pageable. Perangkat mixer tidak memiliki I/O asinkron yang terkait dengannya, sehingga driver ini dapat membuat datanya dapat di-pageable.

Nama bagian data yang dapat dipaginasi harus dimulai dengan empat huruf "PAGE" dan dapat diikuti hingga empat karakter untuk mengidentifikasi bagian secara unik. Empat huruf pertama dari nama bagian (yaitu, "PAGE") harus dikapitalisasi.

Hindari menetapkan nama yang identik ke bagian kode dan data. Untuk membuat kode sumber lebih mudah dibaca, pengembang driver biasanya menetapkan nama PAGE ke bagian kode yang dapat dipaginasi karena nama ini pendek dan mungkin muncul di banyak arahan pragma alloc_text. Nama yang lebih panjang kemudian ditetapkan ke bagian data yang dapat dipaginasi (misalnya, PAGEDATA untuk data_seg, PAGEBSS untuk bss_seg, dan sebagainya) yang mungkin diperlukan driver.

Misalnya, dua arahan pragma pertama dalam contoh kode berikut menentukan dua bagian data yang dapat dipaginasi, PAGEDATA dan PAGEBSS. PAGEDATA dinyatakan menggunakan arahan pragma data_seg dan berisi data yang diinisialisasi. PAGEBSS dinyatakan menggunakan arahan pragma bss_seg dan berisi data yang tidak diinisialisasi.

#pragma data_seg("PAGEDATA")
#pragma bss_seg("PAGEBSS")

INT Variable1 = 1;
INT Variable2;

CHAR Array1[64*1024] = { 0 };
CHAR Array2[64*1024];

#pragma data_seg()
#pragma bss_seg()

Dalam contoh kode ini, Variable1 dan Array1 secara eksplisit diinisialisasi dan oleh karena itu ditempatkan di bagian PAGEDATA. Variable2 dan Array2 secara implisit diinisialisasi nol dan ditempatkan di bagian PAGEBSS.

Menginisialisasi variabel global secara implisit menjadi nol mengurangi ukuran file yang dapat dieksekusi pada disk dan lebih disukai daripada inisialisasi eksplisit menjadi nol. Inisialisasi nol eksplisit harus dihindari kecuali jika diperlukan untuk menempatkan variabel di bagian data tertentu.

Untuk membuat residen memori bagian data dan menguncinya dalam memori, driver memanggil MmLockPagableDataSection, meneruskan item data yang muncul di bagian data yang dapat dipaginasi. MmLockPagableDataSection mengembalikan handel yang akan digunakan dalam permintaan penguncian atau pembukaan kunci berikutnya.

Untuk memulihkan status pageable bagian terkunci, panggil MmUnlockPagableImageSection, meneruskan nilai handel yang dikembalikan oleh MmLockPagableCodeSection atau MmLockPagableDataSection, sebagaimana mewajibkan. Rutinitas Unload driver harus memanggil MmUnlockPagableImageSection untuk melepaskan setiap handel yang telah diperolehnya untuk bagian kode dan data yang dapat dikunci.

Mengunci bagian adalah operasi yang mahal karena manajer memori harus mencari daftar modul yang dimuat sebelum mengunci halaman ke dalam memori. Jika driver mengunci bagian dari banyak lokasi dalam kodenya, driver harus menggunakan MmLockPagableSectionByHandle yang lebih efisien setelah panggilan awal ke BagianXxxMmLockPagable.

Handel yang diteruskan ke MmLockPagableSectionByHandle adalah handel yang dikembalikan oleh panggilan sebelumnya ke MmLockPagableCodeSection atau MmLockPagableDataSection.

Manajer memori mempertahankan hitungan untuk setiap handel bagian dan menaikkan jumlah ini setiap kali driver memanggil MmLockPagableXxx untuk bagian tersebut. Panggilan ke MmUnlockPagableImageSection mengurangi hitungan. Meskipun penghitung untuk handel bagian apa pun bukan nol, bagian tersebut tetap terkunci dalam memori.

Handel ke bagian valid selama drivernya dimuat. Oleh karena itu, driver harus memanggil MmLockPagableXxxSection hanya satu kali. Jika driver memerlukan panggilan penguncian tambahan, driver harus menggunakan MmLockPagableSectionByHandle.

Jika driver memanggil rutinitas MmLockPagableXxx untuk bagian yang sudah dikunci, manajer memori akan menaikkan jumlah referensi untuk bagian tersebut. Jika bagian di-page out saat rutinitas kunci dipanggil, halaman manajer memori di bagian dan mengatur jumlah referensinya menjadi satu.

Menggunakan teknik ini meminimalkan efek driver pada sumber daya sistem. Ketika driver berjalan, driver dapat mengunci ke dalam memori kode dan data yang harus menjadi residen. Ketika tidak ada permintaan I/O yang luar biasa untuk perangkatnya, (yaitu, ketika perangkat ditutup atau jika perangkat tidak pernah dibuka), driver dapat membuka kunci kode atau data yang sama, membuatnya tersedia untuk di-paged out.

Namun, setelah driver terhubung mengganggu, kode driver apa pun yang dapat dipanggil selama pemrosesan interupsi harus selalu menjadi residen memori. Meskipun beberapa driver perangkat dapat dibuat dapat di-pageable atau dikunci ke dalam memori sesuai permintaan, beberapa set inti kode dan data driver tersebut harus secara permanen tinggal di ruang sistem.

Pertimbangkan panduan implementasi berikut untuk mengunci kode atau bagian data.

  • Penggunaan utama rutinitas Mm(Un)LockXxx adalah mengaktifkan kode atau data yang biasanya tidak di-halaman dan dibawa sebagai kode atau data yang tidak dipagasi. Driver seperti driver serial dan driver paralel adalah contoh yang baik: jika tidak ada handel terbuka ke perangkat yang dikelola driver seperti itu, bagian kode tidak diperlukan dan dapat tetap di-page out. Pengalih dan server juga merupakan contoh driver yang baik yang dapat menggunakan teknik ini. Ketika tidak ada koneksi aktif, kedua komponen ini dapat di-page out.

  • Seluruh bagian yang dapat di-pageable dikunci ke dalam memori.

  • Satu bagian untuk kode dan satu untuk data per driver efisien. Banyak bagian bernama dan dapat dipertanyakan umumnya tidak efisien.

  • Pisahkan bagian dan halaman yang murni tetapi dikunci sesuai permintaan.

  • Ingatlah bahwa MmLockPagableCodeSection dan MmLockPagableDataSection tidak boleh sering dipanggil. Rutinitas ini dapat menyebabkan aktivitas I/O berat ketika manajer memori memuat bagian. Jika driver harus mengunci bagian dari beberapa lokasi dalam kodenya, driver harus menggunakan MmLockPagableSectionByHandle.