La lecture et l'écriture de données par l'intermédiaire d'un tuyau
J'ai créé deux processus avec fork(). L'enfant est en train de produire et de l'écriture en continu une quantité variable de données (tableau de char) à la pipe. Le processus parent lit le canal et affiche les données reçues vers stdout.
Le code est très simple:
switch (fork()) {
case -1:
exit (1);
break;
case 0:
close(fd[0]);
generate_data(fd[1]);
break;
default:
close(fd[1]);
while(1) {
n = read(fd[0], readbuffer, sizeof(readbuffer));
readbuffer[n] = 0;
if (n > 0)
printf ("read: %s\n", readbuffer);
else
exit(1);
}
break;
}
Où generate_data(int)
itère sur une liste, l'écriture de chaque élément (string) pour le descripteur de fichier donné en argument (l'écriture, à la fin de la pipe dans ce cas):
void generate_data(int fd)
{
node_t node* = list;
while (node != NULL) {
write(fd, node->data, strlen(node->data)+1);
node = node->next();
}
}
Le problème ici est que la sortie est toujours imprévisible: le processus de l'enfant écrit des données dans la conduite, l'autre est du traitement de la dernière read
, donc quand il invite à relire le reste des données n'est plus là.
Selon man 2 pipe
, cela ne devrait pas se produire:
Les données écrites à l'écriture, à la fin de la pipe est tempérée par l'
noyau jusqu'à ce qu'il est lu à partir de la fin de lecture de la pipe.
De prendre une liste de 10 éléments, certains exemples de sortie:
Exemple 1:
read: element_4
read: element_8
read: element_9
Exemple 2:
read: element_7
read: element_8
read: element_9
read: element_10
Exemple 3:
read: element_2
read: element_8
Quelqu'un a une idée de ce qui se passe ici?
- Pas sans le code indiquant l'écriture, et peut-être quelques exemple de sortie.
- Quel est le problème exactement? Mineur pinaille: read() ne lit pas null cordes. votre de format %s s'attend à une chaîne terminée par le caractère nul. Peut-être que vous devriez ajouter "readbuffer[n] = 0;" après la lecture, étant donné le manque d'espace.
- Merci pour les commentaires. J'ai juste modifié la question avec plus d'information.
- Lire ma réponse soigneusement -- il explique exactement ce qu'est le problème, et votre code ci-dessus le confirme.
generate_data
est le fait d'envoyer plusieurs 0 chaînes terminées au cours de la pipe;printf
est juste l'impression de la première. Remplacer les zéros par des retours à la ligne dansgenerate_data
, ou de les analyser dans votre lecture de code. Mais l'essentiel, c'est queprintf
est ignorant la plupart de ce que vous donnez, car il arrête l'impression lors de la première de 0 octet.
Vous devez vous connecter pour publier un commentaire.
Vous appelez
read
et capture de la valeur de retour, mais alors vous ignorer en grande partie; c'est vous dire combien valide d'octets dansreadbuffer
, mais vous avez à traiterreadbuffer
comme si elle contient un zéro chaîne terminée, ce qui n'est pas nécessairement. En fait, un seulread
peut vous donner plusieurs zéro des chaînes terminées, si vos données-processus d'écriture est de l'envoi de0
octets dans le tuyau; à l'aide deprintf
signifie que vous êtes ignorant la deuxième et les suivantes. À tout le moins, vous devrez utiliserfwrite
à écrire spécifiques, nombre d'octets de sortie standard (stdout), bien que je soupçonne que vous aurez vraiment besoin de faire est de remplacer ces zéros avec des retours à la ligne en premier. Il pourrait être une meilleure idée de modifiergenerate_data
pour envoyer des retours à la ligne au lieu de zéros.read()
d'appel, mais le code n'imprime que le premier string et ignore le reste, il semble comme si ils ont été perdus.0
octets dans le tuyau; ils sont dans le milieu de la data!readbuffer[n] = 0
juste après la lecture. Désolé. Mais de toute façon, le problème est toujours là.De lecture ne s'arrête pas à nul personnage, vous pouvez lire deux "messages" dans un read() de l'appel. Si votre lecteur a vérifier si il n'y a plus de données après le premier 0 (dans le n octets lus), et de l'enregistrer. Une prochaine lecture appel doit ajouter ses données à ce les restes. Un cas particulier est quand il y a un reste, mais pas encore de message dans le tampon.