Détermine la taille d’un tube sans appeler read ()

J’ai besoin d’une fonction appelée SizeOfPipe () qui devrait renvoyer la taille d’un tube. Je veux seulement savoir combien de données se trouve dans le tube et ne pas lire les données sur le tube lui-même.

Je pensais que le code suivant fonctionnerait

fseek (pPipe, 0 , SEEK_END); *pBytes = ftell (pPipe); rewind (pPipe); 

mais fseek dosent travail sur les descripteurs de fichiers. Une autre option consisterait à lire le tuyau, puis à écrire les données en retour, mais vous voudriez éviter cela, si possible, des suggestions?

En fonction de votre implémentation Unix, ioctl / FIONREAD peut faire l’affaire

 err = ioctl (pipedesc, FIONREAD, & bytesAvailable);

À moins que cela ne renvoie le code d’erreur pour “argument non valide” (ou toute autre erreur), bytesAvailable contient la quantité de données disponibles pour débloquer les opérations de lecture à ce moment.

Malheureusement, le système ne peut pas toujours connaître la taille d’un canal – par exemple, si vous transformez un processus de longue durée en une autre commande, le processus source n’a peut-être pas encore été exécuté. Dans ce cas, il n’y a pas de moyen possible (même en théorie) de savoir combien de données vont en sortir.

Si vous souhaitez connaître la quantité de données actuellement disponibles pour la lecture du canal, cela peut être possible, mais cela dépendra de la mise en mémoire tampon du système d’exploitation et d’autres facteurs difficiles à contrôler. L’approche la plus courante consiste simplement à continuer à lire jusqu’à ce qu’il n’y ait plus rien à venir (si vous n’obtenez pas d’EOF, le processus source n’est pas encore terminé). Cependant, je ne pense pas que ce soit ce que vous recherchez.

J’ai donc peur qu’il n’y ait pas de solution générale.

Certaines implémentations UNIX renvoient le nombre d’octets pouvant être lus dans le champ st_size après l’appel de fstat() , mais ce n’est pas portable.

Il n’est généralement pas possible de connaître la quantité de données que vous pouvez lire à partir d’un tuyau uniquement à partir de la poignée du tuyau. Les données peuvent provenir d’un réseau ou être générées dynamicment par un autre processus. Si vous avez besoin de savoir à l’avance, vous devez faire en sorte que les informations vous soient envoyées – par le canal ou hors bande – par n’importe quel processus situé à l’autre extrémité du canal.

Il n’y a pas de moyen générique et portable pour savoir combien de données sont disponibles dans un tube sans le lire. Au moins pas sous les spécifications POSIX.

Les tuyaux ne sont pas recherchables, et il n’est pas possible non plus de replacer les données dans l’extrémité de lecture d’un tuyau.

Des astuces spécifiques à la plate-forme peuvent cependant être possibles. Si votre question est spécifique à une plate-forme, l’édition de votre question pour le dire pourrait améliorer vos chances d’obtenir une réponse fonctionnelle.

Il n’est presque jamais nécessaire de savoir combien d’octets se trouvent dans le tube: peut-être voulez-vous simplement faire une lecture non bloquante () sur le tube, c’est-à-dire. pour vérifier si des octets sont prêts, et si oui, lisez-les, mais ne vous arrêtez jamais et attendez que le canal soit prêt.

Vous pouvez le faire en deux étapes. Tout d’abord, utilisez l’appel système select () pour savoir si des données sont disponibles ou non. Un exemple est ici: http://www.developerweb.net/forum/showthread.php?t=2933

Deuxièmement, si select indique que les données sont disponibles, appelez read () une fois, et une seule fois, avec une grande taille de bloc. Il ne lira que le nombre d’octets disponibles ou la taille de votre bloc, selon la taille la plus petite. Si select () renvoie true, read () retournera toujours tout de suite.

Je ne pense pas que ce soit possible, ce n’est pas le point d’un tuyau pour fournir une communication interprocessus entre les deux extrémités (dans une direction). Si je suis correct dans cette assertion, l’envoi n’a peut-être pas encore fini de pousser les données dans le tube – il serait donc impossible de déterminer la longueur.

Quelle plateforme utilises-tu?

Je ne pense pas que ce soit possible. Pipes présente un protocole orienté stream plutôt que orienté paquet. IOW, si vous écrivez deux fois dans un tube, une fois avec, disons, 250 octets et une fois avec, disons, 520 octets, il est impossible de déterminer le nombre d’octets que vous obtiendrez de l’autre côté dans une requête de lecture. Vous pourriez obtenir 256, 256, puis le rest.

Si vous avez besoin d’imposer des paquets sur un canal, vous devez le faire vous-même en écrivant un nombre d’octets prédéterminé (ou délimité) en tant que longueur de paquet, puis le rest du paquet. Utilisez select () pour savoir s’il y a des données à lire, utilisez read () pour obtenir un tampon de taille raisonnable. Lorsque vous avez votre tampon, il vous incombe de déterminer la limite du paquet.

Si vous souhaitez connaître la quantité de données attendue, vous pouvez toujours écrire au début de chaque msg envoyé par les tubes à la taille du msg. Donc, écrivez par exemple 4 octets au début de chaque msg avec la longueur de vos données, puis lisez seulement les 4 premiers octets.

Il n’y a pas de moyen portable pour déterminer la quantité de données provenant d’un canal. La seule chose que vous pouvez faire est de lire et de traiter les données à mesure qu’elles arrivent.

Pour cela, vous pourriez utiliser quelque chose comme un tampon circulaire

Vous pouvez l’envelopper dans un object avec un tampon pouvant être rembobiné. Cela ne serait possible que pour de petites quantités de données.

Une façon de faire cela en C consiste à définir le stuct et à envelopper toutes les fonctions fonctionnant sur des tuyaux pour votre structure.

Sous Windows, vous pouvez toujours utiliser PeekNamedPipe , mais je doute que ce soit ce que vous voulez faire de toute façon.