J'ai rencontré des problèmes lors de l'utilisation de tuyaux et de processus enfants.Le tuyau et la fourche entraînent une sortie incorrecte et désordonnée
I doivent
- créer quatre fils avec fork()
- établir tuyau en utilisant une communication à deux voies() entre le parent et chaque enfant
- lire les données d'un certain nombre de fichiers contenant card.txt des chaînes
- cordes distribuer de manière ronde à chaque enfant ABCDEFGH, enfant 1 obtenir AE, enfant 2 get BF et ainsi de suite
- sélectionner une variable membre -> se nd variable parent à l'aide d'écriture() et lire() et close() pour fermer tuyau utilisé fin
- impression reçu variable processus parent
Une sortie attendue est:
$ ./a.out 1C < card.txt
Child : 1, pid 1593 :
<S2 S3 S9 ><H9 H6 HA H8 ><C6 CK ><D8 DQ D7 D3 >
Child : 2, pid 1594 :
<SA S6 S7 S4 ><H4 HJ H7 ><CQ C9 CT ><DT D2 D9 >
Child : 3, pid 1595 :
<SQ S5 ><H2 ><C7 C5 C8 CA C4 CJ C3 ><DA D5 >
Child : 4, pid 1596 :
<S8 SJ SK ST ><HK HT H5 H3 HQ ><C2 ><D4 D6 >
child 1: H9
parent: child 1 played H9
child 2: CQ
parent: child 2 played CQ
child 3: H2
parent: child 3 played H2
child 4: HK
parent: child 4 played HK
Cependant, la sortie réelle est la suivante:
parent: child 1 played (null)parent: child 2 played (null)parent: child 3 played (null)parent: child 4 played (null)
Pourquoi est-ce? Comment résoudre le problème?
Le code créé cette sortie:
#include <stdio.h>
#include <string.h>
#define BUFFERSIZE 51
int i=0;
int currpid, s;
char *buf[BUFFERSIZE];
char *array[BUFFERSIZE];
int n;
char *buffer[100];
/** child to parent pipe */
int child_parent[2];
/** parent to child pipe */
int parent_child[2];
/** child2 to parent pipe */
int child2_parent[2];
/** parent to child2 pipe */
int parent_child2[2];
/** child3 to parent pipe */
int child3_parent[2];
/** parent to child3 pipe */
int parent_child3[2];
/** child4 to parent pipe */
int child4_parent[2];
/** parent to child4 pipe */
int parent_child4[2];
void childFunction(){
int j;
for(i = s+1; i < BUFFERSIZE; i += 4)
{
buf[j] = array[i];
j++;
}
printf("\n<");
int r;
char *e;
for(r = 0; r < j; r++)
{
int index;
e = strchr(buf[r],'S');
if (e!=NULL){
index = (int)(e-buf[r]);
if (index == 0){
printf("%s ", buf[r]) ;
}
}
}
printf(">");
printf("<");
for(r = 0; r < j; r++)
{
int index;
e = strchr(buf[r],'H');
if (e!=NULL){
index = (int)(e-buf[r]);
if (index == 0){
printf("%s ", buf[r]) ;
}
}
}
printf(">");
printf("<");
for(r = 0; r < j; r++)
{
int index;
e = strchr(buf[r],'C');
if (e!=NULL){
index = (int)(e-buf[r]);
if (index == 0){
printf("%s ", buf[r]) ;
}
}
}
printf(">");
printf("<");
for(r = 0; r < j; r++)
{
int index;
e = strchr(buf[r],'D');
if (e!=NULL){
index = (int)(e-buf[r]);
if (index == 0){
printf("%s ", buf[r]) ;
}
}
}
printf(">\n");
switch (s){
case 0:
close(parent_child[1]);
close(parent_child[0]);
close(child_parent[0]);
buffer[0] = buf[0];
printf("child %d: %s", s+1, buffer[0]);
write(child_parent[1], &buffer[0], strlen(buffer[0]));
close(child_parent[1]);
break;
case 1:
close(parent_child2[1]);
close(parent_child2[0]);
close(child2_parent[0]);
buffer[0] = buf[0];
printf("child %d: %s", s+1, buffer[0]);
write(child2_parent[1], &buffer[0], strlen(buffer[0]));
close(child2_parent[1]);
break;
case 2:
close(parent_child3[1]);
close(parent_child3[0]);
close(child3_parent[0]);
buffer[0] = buf[0];
printf("child %d: %s", s+1, buffer[0]);
write(child3_parent[1], &buffer[0], strlen(buffer[0]));
close(child3_parent[1]);
break;
case 3:
close(parent_child4[1]);
close(parent_child4[0]);
close(child4_parent[0]);
buffer[0] = buf[0];
printf("child %d: %s", s+1, buffer[0]);
write(child4_parent[1], &buffer[0], strlen(buffer[0]));
close(child4_parent[1]);
break;
}
}
void parentFunction(){
switch (s){
case 0:
close(child_parent[1]);
close(parent_child[1]);
close(parent_child[0]);
read(child_parent[0],&buffer[0], sizeof(buffer[0]));
printf("parent: child %d played %s", s+1, buffer[0]);
close(child_parent[0]);
break;
case 1:
close(child2_parent[1]);
close(parent_child2[1]);
close(parent_child2[0]);
read(child2_parent[0],&buffer[0], sizeof(buffer[0]));
printf("parent: child %d played %s", s+1, buffer[0]);
close(child2_parent[0]);
break;
case 2:
close(child3_parent[1]);
close(parent_child3[1]);
close(parent_child3[0]);
read(child3_parent[0],&buffer[0], sizeof(buffer[0]));
printf("parent: child %d played %s", s+1, buffer[0]);
close(child3_parent[0]);
break;
case 3:
close(child4_parent[1]);
close(parent_child4[1]);
close(parent_child4[0]);
read(child4_parent[0],&buffer[0], sizeof(buffer[0]));
printf("parent: child %d played %s", s+1, buffer[0]);
close(child4_parent[0]);
break;
}
}
int main(int argc, char *argv[])
{
int ch;
ssize_t rread;
char *line = NULL;
size_t len = 0;
while (rread = getdelim(&line, &len, '\0', stdin) != -1) {
}
array[i] = strtok(line," ");
while(array[i]!=NULL)
{
array[++i] = strtok(NULL," ");
}
int childlimit = 4;
int childpids[childlimit];
int currpid;
if (pipe(child_parent) == 0 && pipe(parent_child) == 0 && pipe(child2_parent) == 0 && pipe(parent_child2) == 0 && pipe(child3_parent) == 0 && pipe(parent_child3) == 0 && pipe(child4_parent) == 0 && pipe(parent_child4) == 0)
{
for(s=0; s<childlimit; s++){
switch(currpid = fork()){
case 0:
printf("Child : %d, pid %d : ", s+1, getpid());
childFunction();
break;
case -1:
printf("Error when forking\n");
return 1;
default:
// in the father
childpids[s] = currpid;
parentFunction();
break;
}
}
//wait for all child created to die
waitpid(-1, NULL, 0);
}
}
Avez-vous entendu parler de ces choses appelées 'fonctions'? Ils sont utiles pour rendre le code plus clair. Il y a beaucoup trop de code pour le traitement de l'enfant dans la fonction principale. Gardez la gestion des processus dans 'main()'; déléguez le traitement de chaîne et les opérations d'E/S à une fonction qui s'exécute uniquement dans les enfants. Vous ne fermez pas assez de descripteurs de fichiers dans les enfants. Vous fermez trop de descripteurs de fichier dans le parent si le parent doit écrire à ses enfants; Si le parent n'a pas besoin d'écrire aux enfants, pourquoi vous embêtez-vous avec les tuyaux de parent à enfants? –
@JonathanLeffler, code mis à jour déplacer le code parent et le code enfant dans différentes fonctions, dans ma mise en œuvre, il faudra écrire parent aux enfants, mais à ce stade, il n'a pas encore été développé en raison du problème. –
L'utilisation de la variable globale 'i' pour les contrôles de boucle dans les fonctions est un désastre. Parfois, les variables globales sont nécessaires - quand elles le sont, vous devriez les utiliser. La plupart du temps, ils ne le sont pas - et quand ils ne le sont pas, vous ne devriez pas les utiliser. Les noms de variables globales à une seule lettre sont rarement appropriés. (Il est préférable de répéter la définition de «i» dans chaque fonction où cela est nécessaire que de faire comme vous l'avez fait.) Cela rend votre code très difficile à analyser. Votre boucle de lecture de chaîne conserve uniquement la dernière 'ligne' ('ligne' terminée par un caractère nul). J'imagine que c'est une façon d'engloutir tout le fichier en une seule opération. –