6
votes

Io Finition Port Key Confusion

J'écris un serveur de port d'achèvement IO ( code source ici ) à l'aide de l'API Windows DLL en Python à l'aide du module CTYPES. Mais c'est une utilisation assez directe de l'API et cette question est dirigée contre ceux qui ont une connaissance de l'IOCP, pas de Python.

Si je comprends la documentation de CreateIocompletionPortPort, vous spécifiez la touche d'achèvement "définie par l'utilisateur" lorsque vous appelez cette fonction avec une poignée de fichier (dans mon cas une prise) que vous associez avec l'IOCP créé. Lorsque vous vous contournez d'appeler GetQuecueComplettionStatus, vous obtenez une valeur de clé d'achèvement avec un pointeur sur un objet superposé. La clé d'achèvement doit identifier ce que l'objet et la demande superposés sont terminés.

Cependant, disons que je passe dans 100 comme clé d'achèvement de mon appel de société CreateIocompletion avec un objet superposé. Lorsque le même objet superposé a terminé son IO terminé et qu'il arrive dans GetQuecueDcompletionStatus, la clé d'achèvement qui l'accompagne est beaucoup plus grande et ne ressemble à aucune ressemblance à la valeur initiale de 100.

suis mal comprendre comment fonctionne la clé d'achèvement ou dois-je le faire mal dans le code source que j'ai lié ci-dessus?


0 commentaires

6 Réponses :


1
votes

getQueSueCompletionStatus renvoie deux choses, un superposé structure et une clé d'achèvement. La clé d'achèvement représente des informations par périphérique et la structure superposée représente des informations par appel. La clé d'achèvement doit correspondre à ce qui a été donnée dans l'appel à CreateIocompletionPort . En règle générale, vous utiliseriez un pointeur sur une structure contenant des informations sur la connexion comme clé d'achèvement.

On dirait que vous ne faites rien avec CompleLeKey comme retourné par GetQueDecPleTionStatus .

Je suppose que vous voulez: xxx

édition:

Python sache en quelque sorte que le Superposé structure créée dans CreeAcceptSocket est utilisé de manière asynchrone par l'API Win32 et l'empêchent d'être GC'D?


1 commentaires

"Disons que je passe dans 100 comme clé d'achèvement de mon appel de sport CreateIocompéion avec un objet superposé. Lorsque le même objet superposé a son io terminé et qu'il arrive dans GetQueDecPleTionnstatus, la clé d'achèvement qui l'accompagne est beaucoup plus grande et ne ressemble à aucune ressemblance. la valeur initiale de 100. " De ma question et pourquoi je ne le comparant pas dans le code source. Vous avez probablement raison à propos de l'objet chevauché obtenu des ordures recueillies, mais cela n'est pas pertinent pour la question.



0
votes

Le problème est dans la façon dont je passe les clés d'achèvement. L'argument de la clé d'achèvement est un pointeur, mais il passe le pointeur et non la valeur indiquée - un peu me déroutant au moins.

Aussi la clé d'achèvement transmise pour la connexion acceptée Le paquet chevauché est celui de la prise d'écoute - pas la prise acceptée.


0 commentaires

4
votes

Ce que j'ai trouvé dans la pratique quotidienne est qu'il est préférable de simplement se concentrer sur le résultat code> superposé code>, comme cela sera inchangé. Une solution que vous pouvez l'utiliser efficacement est d'avoir quelque chose comme ce qui suit:

OVERLAPPED* from_queued_completion_status;
// Actually get a value into from_queued_completion_status

CompletionHandler* handler_for_this_completion = (CompletionHandler*)from_queued_completion_status;
// Have fun!


0 commentaires

0
votes

La clé d'achèvement n'est pas un pointeur - il s'agit d'un nombre de type ULONG_PTR, ce qui signifie simplement "un entier la taille d'un pointeur", de sorte qu'il est de 32 bits sur X86 et 64 bits sur x64. Le typename est confus, mais lorsque Win32 typenames se réfèrent à un pointeur, ils le font en ayant un P à l'avant du nom, pas la fin.


0 commentaires

0
votes

Si votre application est multipliée, assurez-vous que l'achèvement de l'emploi que vous passez est soit une valeur constante, soit une valeur de pointeur pour objecter sur le tas plutôt que sur la pile. Dans votre exemple où 100 est passé aussi constante, vous devez avoir tort de dire n'importe quel changement. Mais quant au problème, il se peut que vous puissiez passer une poignée de prise dans CreateIocompletionPortPort, mais pas une référence à gérer dans GetQuecueDcompletionStatus afin de la revenir. Vous pouvez faire

HANDLE socket;
GetQueuedCompletionStatus(existed_io_completion_port, &io_bytes_done, (PULONG_PTR)&socket, &overlapped);


0 commentaires

2
votes

Vous devriez penser à la clé d'achèvement comme des données «par connexion» et la structure inclinée (étendue) comme opérations «par I / O».

Certaines personnes utilisent une structure superposée étendue pour les deux et stocker toutes les informations dont ils ont besoin dans la structure superposée étendue. J'ai toujours stocké un objet compté de référence qui envoie ma prise dans la clé d'achèvement et une mémoire tampon de données comptée en tant que structure superposée étendue. Si vous êtes intéressé, vous pouvez voir Quelques exemple de code IOCP en C ++ ici .

La clé d'achèvement est, efficacement, juste une poignée opaque aux données que le système d'achèvement d'E / S vous donnera une fois une finition sur la prise.


0 commentaires