Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Sur le système d’exploitation NT, les pilotes sont multithreads ; ils peuvent recevoir plusieurs demandes d’E/S provenant de différents threads en même temps. Lors de la conception d’un pilote, vous devez supposer qu’il sera exécuté sur un système SMP et prendre les mesures appropriées pour garantir l’intégrité des données.
Plus précisément, chaque fois qu’un pilote modifie les données d'objets globaux ou de fichiers, il doit utiliser un verrou ou une séquence interblocée pour empêcher les conditions de concurrence.
Rencontre une condition de concurrence lors du référencement de données spécifiques à l’objet global ou de fichier
Dans l’extrait de code suivant, une condition de course peut se produire lorsque le pilote accède aux données globales dans Data.LpcInfo :
PLPC_INFO pLpcInfo = &Data.LpcInfo; //Pointer to global data
...
...
// This saved pointer may be overwritten by another thread.
pLpcInfo->LpcPortName.Buffer = ExAllocatePool(
PagedPool,
arg->PortName.Length);
Plusieurs threads entrant ce code suite à un appel IOCTL peuvent entraîner une fuite de mémoire lorsque le pointeur est remplacé. Pour éviter ce problème, le pilote doit utiliser les routines ExInterlockedXxx ou un type de verrou lorsqu’il modifie les données globales. Les exigences du pilote déterminent les types acceptables de verrous. Pour plus d’informations, consultez Spin Locks, Kernel Dispatcher Objects et ExAcquireResourceSharedLite.
L’exemple suivant tente de réallouer une mémoire tampon spécifique au fichier (Endpoint-LocalAddress>) pour contenir l’adresse du point de terminaison :
Endpoint = FileObject->FsContext;
if ( Endpoint->LocalAddress != NULL &&
Endpoint->LocalAddressLength <
ListenEndpoint->LocalAddressLength ) {
FREE_POOL (Endpoint->LocalAddress,
LOCAL_ADDRESS_POOL_TAG
);
Endpoint->LocalAddress = NULL;
}
if ( Endpoint->LocalAddress == NULL ) {
Endpoint->LocalAddress =
ALLOCATE_POOL (NonPagedPool,
ListenEndpoint->LocalAddressLength,
LOCAL_ADDRESS_POOL_TAG);
}
Dans cet exemple, une condition de concurrence peut se produire avec des accès à l’objet de fichier. Étant donné que le pilote ne contient aucun verrou, deux requêtes pour le même objet de fichier peuvent entrer cette fonction. Le résultat peut être des références à la mémoire libérée, plusieurs tentatives pour libérer la même mémoire ou les fuites de mémoire. Pour éviter ces erreurs, les deux instructions if doivent être placées dans un verrou de rotation.