2008-09-16 19 views
4

J'ai besoin d'une fonction appelée SizeOfPipe() qui devrait renvoyer la taille d'un tuyau- Je veux seulement savoir combien de données sont dans le tuyau et ne pas lire réellement les données du tuyau lui-même.Déterminer la taille d'un tuyau sans appeler read()

Je pensais que le code suivant travaillerait

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

mais le travail fseek dosent les descripteurs de fichiers. Une autre option serait de lire le tuyau, puis écrire les données en arrière, mais souhaitez éviter cela si possibe, des suggestions?

Répondre

2

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 dynamiquement par un autre processus. Si vous avez besoin de savoir à l'avance, vous devez vous assurer que l'information vous soit envoyée - par le biais du tuyau ou hors de la bande - par tout processus se trouvant à l'autre extrémité du tuyau.

2

Il n'y a pas de façon générique et portable de dire combien de données sont disponibles dans un tuyau sans le lire. Au moins pas sous les spécifications POSIX.

Les tuyaux ne sont pas recherchés, et il n'est pas non plus possible de remettre les données dans l'extrémité de lecture d'un tuyau.

Des astuces spécifiques à la plate-forme pourraient être possibles, cependant. Si votre question est spécifique à une plate-forme, éditer votre question pour le dire pourrait améliorer vos chances d'obtenir une réponse de travail.

0

Je ne pense pas que ce soit possible, n'est-ce pas le point d'un tuyau de 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 plate-forme utilisez-vous?

4

Malheureusement, le système ne peut pas toujours connaître la taille d'un canal. Par exemple, si vous acheminez un processus de longue durée vers une autre commande, il est possible que le processus source n'ait pas encore fini de s'exécuter. Dans ce cas, il n'y a pas moyen (même en théorie) de savoir combien de données vont en sortir.

Si vous voulez connaître la quantité de données actuellement disponible disponible pour lire sur le tuyau qui pourrait être possible, mais cela dépendra de la mise en mémoire tampon du système d'exploitation et d'autres facteurs qui sont difficiles à contrôler. L'approche la plus courante ici est de continuer à lire jusqu'à ce qu'il n'y ait plus rien à faire (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 cherchez. J'ai donc peur qu'il n'y ait pas de solution générale.

4

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

0

Je ne pense pas que ce soit possible. Les tuyaux présentent un protocole orienté flux plutôt qu'un paquet orienté paquet. IOW, si vous écrivez deux fois dans une pipe, une fois avec, disons, 250 octets et une fois avec, disons, 520 octets, il n'y a aucun moyen de dire combien d'octets vous obtiendrez de l'autre bout dans une requête de lecture. Vous pourriez obtenir 256, 256, et le reste.

Si vous devez 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é) comme longueur de paquet, puis le reste 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 est de votre responsabilité de déterminer la limite de paquet.

0

Si vous voulez connaître la quantité de données attendues, vous pouvez toujours écrire au début de chaque msg envoyé par les pipes 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.

14

En fonction de votre implémentation unix ioctl/FIONREAD pourrait faire l'affaire

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

À moins que ce renvoie le code d'erreur « argument invalide » (ou toute autre erreur) bytesAvailable contient la quantité de données disponibles pour débouchage lecture opérations à ce moment-là.

2

Il n'est presque jamais nécessaire de connaître le nombre d'octets contenus dans le tube: vous souhaitez peut-être effectuer une lecture() non bloquante sur le tube, par exemple. pour vérifier s'il y a des octets prêts, et si oui, lisez-les, mais n'arrêtez jamais et attendez pour que le tuyau soit prêt.

Vous pouvez le faire en deux étapes. Commencez par utiliser l'appel système select() pour savoir si les 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 taille de bloc importante. Il lira seulement autant d'octets sont disponibles, ou jusqu'à la taille de votre bloc, selon la plus petite. Si select() renvoie true, read() retournera toujours tout de suite.

0

Il n'y a pas de façon portable de dire la quantité de données provenant d'un tuyau. La seule chose que vous pouvez faire est de lire et de traiter les données telles qu'elles sont.

Pour cela, vous pouvez utiliser quelque chose comme un circular buffer

0

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

0

Vous pouvez l'enrouler dans un objet avec un tampon pouvant être rembobiné. Cela ne serait faisable que pour de petites quantités de données.

L'une des façons de faire cela en C est de définir l'enchaînement et d'envelopper toutes les fonctions fonctionnant sur les tuyaux de votre structure.