2

Je travaille actuellement sur un mécanisme IPC basé sur des canaux nommés utilisant un port d'achèvement d'E/S.Quand les paquets de port d'E/S sont-ils envoyés et quand?

Malheureusement, j'ai quelques problèmes avec la documentation msdn car je ne comprends pas très bien dans quels cas les appels à ReadFile/WriteFile aboutissent à un paquet d'achèvement.

Le cas où FALSE est retourné avec ERROR_IO_PENDING est clair, mais qu'en est-il du cas apparemment possible, lorsque ERROR_MORE_DATA est renvoyé? Y aura-t-il un paquet d'achèvement dans ce cas? De plus, que faire si d'autres erreurs sont renvoyées? Dans quels cas dois-je gérer le résultat et libérer des ressources directement et pas dans le gestionnaire de complétion?

Un autre cas serait de savoir si ReadFile/WriteFile réussit même, ce qui est apparemment aussi possible. MSDN est heureusement assez clair sur ce here:

De plus, la fonction WriteFile peuvent parfois renvoyer TRUE avec une valeur GetLastError de ERROR_SUCCESS, même si elle utilise une poignée asynchrone (qui peut également retourner FAUX avec ERROR_IO_PENDING). ... Dans cet exemple, la recommandation consisterait à autoriser la routine de port d'achèvement à être seule responsable de toutes les opérations de libération de ces ressources.

Est-ce cette recommandation correcte dans tous les cas, et le résultat d'une opération ReadFile/WriteFile pour les poignées affectées à un port d'achèvement pourrait (et devrait) être complètement ignoré en fait, parce qu'un paquet est envoyé au port de toute façon ?

Répondre

2

Il y aura un élément de fin d'E/S mis en file d'attente pour une opération E/S à chaque fois que l'opération E/S peut démarrer. Indépendamment du fait qu'une erreur soit rencontrée ou non après le démarrage de l'opération d'E/S, un élément d'achèvement est mis en file d'attente sur le port d'achèvement.

Il existe un problème de mappage entre les codes NTSTATUS renvoyés par le système IO et les codes d'erreur Win32, ce qui rend difficile la détermination des statuts qui sont des erreurs et qui sont simplement informatifs. NTSTATUS, qui est utilisé par le noyau et l'API native, a quatre niveaux de gravité: succès, information, avertissement et erreur. Tout sauf un code d'erreur indiquerait que l'opération E/S a pu démarrer. Win32 a seulement une gravité (ERROR_*), donc les codes de succès, d'information et d'avertissement ont dû être mappés avec les codes d'erreur.

  • ERROR_IO_PENDING - STATUS_PENDING est un état de réussite
  • ERROR_MORE_DATA-STATUS_BUFFER_OVERFLOW un avertissement ou STATUS_MORE_ENTRIES un état de réussite

Vous pouvez ignorer tous les codes non-erreur que le retour ReadFile ou WriteFile et attendre une fin en file d'attente article, mais en déterminant qui est ce qui peut être un peu douloureux. Ce serait bien si les codes d'erreur Win32 étaient mieux organisés, mais Microsoft fournit un mappage des codes d'erreur NTSTATUS à Win32: http://support.microsoft.com/kb/113996. Voir ntstatus.h dans la plate-forme SDK ou votre installation VS pour déterminer la gravité d'un code NTSTATUS.

Il est possible que l'opération d'E/S soit terminée lorsque l'appel d'API d'origine revient, par ex. une requête de lecture qui vient d'être copiée hors du cache (rien à attendre de manière asynchrone). Un message d'achèvement sera toujours mis en file d'attente dans de tels cas pour des raisons de cohérence.

0
  • Oui, il est tout à fait possible que ERROR_MORE_DATA pourrait trouver dans un paquet d'achèvement. Vous devriez toujours être prêt à gérer les erreurs potentielles. Dans la documentation pour GetQueuedCompletionStatus il est clair que quand il renvoie FALSE, vous devriez vérifier si le paramètre lpOverlapped est NULL. Si ce n'est pas NULL, le paquet d'achèvement d'E/S contient une erreur.

  • Le comportement par défaut est pour un paquet d'achèvement à la file d'attente jusqu'au port d'achèvement, même lorsque ReadFile ou WriteFile retour TRUE. À partir de Windows Vista, cette politique peut être modifiée. Voir la documentation au SetFileCompletionNotificationModes.