Nota
L'accesso a questa pagina richiede l'autorizzazione. Puoi provare ad accedere o a cambiare directory.
L'accesso a questa pagina richiede l'autorizzazione. Puoi provare a cambiare directory.
Il problema di I/O diretto più comune non riesce a gestire correttamente i buffer di lunghezza zero. Poiché il gestore di I/O non crea mdls per i trasferimenti di lunghezza zero, un buffer di lunghezza zero restituisce un valore NULL in Irp-MdlAddress>.
Per eseguire il mapping dello spazio degli indirizzi, i driver devono usare MmGetSystemAddressForMdlSafe, che restituisce NULL se il mapping ha esito negativo, ad esempio se un driver passa un NULLMdlAddress. I driver devono sempre verificare la presenza di un valore NULL restituito prima di tentare di usare l'indirizzo restituito.
L'I/O diretto comporta il doppio mapping dello spazio indirizzi dell'utente a un buffer di indirizzi di sistema, in modo che due indirizzi virtuali diversi abbiano lo stesso indirizzo fisico. Il doppio mapping ha le conseguenze seguenti, che talvolta possono causare problemi per i driver:
L'offset nella pagina virtuale dell'indirizzo dell'utente diventa l'offset nella pagina di sistema.
L'accesso oltre la fine di questi buffer di sistema può andare inosservato per lunghi periodi di tempo a seconda della granularità della pagina della mappatura. A meno che il buffer di un chiamante non venga allocato alla fine di una pagina, i dati scritti oltre la fine del buffer verranno comunque visualizzati nel buffer e il chiamante non sarà a conoscenza di eventuali errori. Se la fine del buffer coincide con la fine di una pagina, gli indirizzi virtuali di sistema oltre la fine potrebbero puntare a qualsiasi elemento o potrebbero non essere validi. Tali problemi possono essere estremamente difficili da trovare.
Se il processo chiamante ha un altro thread che modifica il mapping dell'utente della memoria, il contenuto del buffer di sistema cambierà quando cambia il mapping della memoria dell'utente.
In questo caso, l'uso del buffer di sistema per archiviare i dati scratch può causare problemi. Due recupero dalla stessa posizione di memoria potrebbero produrre valori diversi.
Il frammento di codice seguente riceve una stringa in una richiesta di I/O diretta, quindi tenta di convertire tale stringa in caratteri maiuscoli:
PWCHAR PortName = NULL; PortName = (PWCHAR)MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); // // Null-terminate the PortName so that RtlInitUnicodeString will not // be invalid. // PortName[Size / sizeof(WCHAR) - 1] = UNICODE_NULL; RtlInitUnicodeString(&AdapterName, PortName);Poiché il buffer potrebbe non essere formato correttamente, il codice tenta di forzare un valore NULL Unicode come ultimo carattere di buffer. Tuttavia, se la memoria fisica sottostante è doppiamente mappata a un indirizzo utente e a un indirizzo di modalità kernel, un altro thread nel processo può sovrascrivere il buffer non appena l'operazione di scrittura è completata.
Viceversa, se il valore NULL non è presente, la chiamata a RtlInitUnicodeString può superare l'intervallo del buffer ed eventualmente causare un controllo del bug se non rientra nel mapping di sistema.
Se un driver crea ed esegue il mapping del proprio MDL, deve assicurarsi che acceda al file MDL solo con il metodo per cui è stato eseguito il probe. Ovvero, quando il driver chiama MmProbeAndLockPages, specifica un metodo di accesso (IoReadAccess, IoWriteAccess o IoModifyAccess). Se il driver specifica IoReadAccess, non deve tentare successivamente di scrivere nel buffer di sistema reso disponibile da MmGetSystemAddressForMdl o MmGetSystemAddressForMdlSafe.