J'utilise une taille fixe dans fgets parceque je ne sais pas comment faire autrement.
Comment lui dire de lire jusqu'au caratère '\n'.
Version imprimable
J'utilise une taille fixe dans fgets parceque je ne sais pas comment faire autrement.
Comment lui dire de lire jusqu'au caratère '\n'.
Comment est ton fichier de départ (celui dans lequel on lit x lignes) ?
S'il s'agit d'un fichier composé de lignes de moins de 31 caractères terminées par un '\n', utilise effectivement fgets. Dans ce cas, écris dans le fichier cible par fputs (ou éventuellement fwrite comme tu le proposes).
J'ai remarqué aussi que tous tes processus fils écrivent dans le même fichier.
Celui-ci est ouvert en mode "w". C'est le dernier fils qui effectuera le fwrite qui l'emportera !
Pour que plusieurs processus écrivent dans le même fichier, il te faut gérer leur synchronisation (par la fonction lockf sous Unix par exemple).
Réponse à ta question sur fgets:
fgets s'arrête automatiquement au '\n'. Tu dois juste lui donner la taille maximale de la zonde de réception (afin qu'il n'y ait pas de débordement).
Ton appel est donc correct.
Je souhaiterais que le programme marche avec une taille de ligne indefinie donc eventuellement plus grande que 31.// désolé j'avais pas vu que t'avais répondu
Pour les fils je souhaite qu'ils écrivent tous dans le même fichier, je devrais mettre "a" alors, c'est bien ça?
Pour ce qui de la synchronisation, je la réaliserai par la suite par d'autre fonctions. C'est pour cela que pour l'instant je ne crée qu'un seul fils.
Pour les fils, utilises la fonction lockf pour verrouiller le fichier.
ex (sans la gestion des retours des fonctions appelées):
Code:
1
2
3
4
5
6
7
8
9 int fd; fd = open(filename,O_WRONLY|O_CREAT,mode); /* mode à définir en fonction des permissions que tu souhaites accorder */ lseek(fd,0L,SEEK_SET); lockf(fd,F_LOCK,0); write(fd,text,strlen(text)); lseek(fd,0L,SEEK_SET); lockf(fd,F_ULOCK,0); close(fd);
En fait le programme doit simuler un mécanisme d' IPC.
Donc une fois que le père aura séparé le fichier en paquet de x lignes,
Il va créer pour chaque paquet de lignes un fils. Lorsque tous les fils sont créé, le père crée un fichier dans lequel il écrit le pid du premier fils. Dès que ce fils se termine le père efface l'ancien pid et écrit celui du fils suivant.
Les fils eux doivent verifier si c'est leur pid qui est inscrit dans le fichier, si c'est le cas il affiche leur paquet de lignes et l'écrivent dans le fichier destination sinon le processus sleep.
Et donc chaque fils écrira à la suite du fichier, et le fichier sera reconstitué.
J'espere que j'ai été assez clair.
Oui, c'est clair. Dans ce cas, utilise effectivement un fopen(...,"a");
Merci, part contre il ne se passe rien lorsque je lance l'executable.
Sauf à la complialtion il me préviens que ma fonction read_file_and_creat_child renvoie une variable local. Mais bon je ne vois pas le problème. Qu'en pense tu?
effectivement, p est un tableau.
return p retourne donc l'adresse d'une variable sur la pile. Cette variable n'est plus valide quand tu sors de ta fonction.
Récupère donc les pid par l'intermédiaire d'une variable passée à ta fonction:
ex:
dans le main (je te laisse gérer les codes retour des fonctions):
dans ta fonction:Code:
1
2
3
4
5 int *PID; PID = (int *) malloc(n*sizeof(int)); /* non pas (int *) comme je l'avais mis précédemment */ read_file_and_create_childs(argv[2], argv[3], n, 1,PID); free(PID);
Code:
1
2
3
4
5
6 int *read_file_and_create_childs(char *srcname, char *dstname, int x, int nbprocs,int *PID) { ... while(i<nbprocs) { PID[i] = create_new_child(...
Merci , part contre comment se fait - il que rien ne s'affiche et qu'aucun perror ne se soit manifesté?
Je vais essayer de mettre des printf un peu partout, histoire de voir se qui se passe.
En fait j'avais oublier de réinisialiser le i avant le while.
Par contre j'ai un autre problème, lorsque j'ouvre avec fopen(.."a")
qu'ensuite j'écris avec fwrite, que je ferme, puis que j'ouvre à nouveau avec fopen(.."a") ----> illegal seek.
Je pense justement qu'avec le mode "a" on reprenant là où on s'etait arreté dans le fichier, tu ne pense pas?
En principe, oui !
Peux tu remettre ton code ?
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define TAILLE_LIGNE 32 #define NB_LIGNES 60 // lit x lignes et les place dans le buffer int read_x_lines(FILE *file, char **buffer, int x) { int nb_lignes_lues = 0; int i=0; while((fgets(buffer[i],TAILLE_LIGNE,file))!= NULL && i<x) { nb_lignes_lues++; i++; } /* for(i=0;i<NB_LIGNES;i++) printf(" %s \n",buffer[i]);*/ return nb_lignes_lues; } // crée un fils en lui transmettant une chaine de caractère qu'il devra afficher et écrire dans le fichier "filename" int create_new_child(char *text, char *filename) { pid_t fils; printf(" Creation du fils \n"); fils = fork(); switch(fils) { case -1 : { perror(" fork "); exit(1); } case 0 : { printf(" %s \n",text); FILE *fd; if((fd=fopen(filename,"a")) == NULL); { perror(" fopen "); exit(1); } if(fwrite(text,strlen(text), 1, fd) == 0) { perror(" write "); exit(1); } fclose(fd); exit(0); } default : { wait((int*)0); return fils; } } } int *read_file_and_create_childs(char *srcname, char *dstname, int x, int *nbprocs) { int i = 0; int nbll; char **buffer; buffer = (char **)malloc(NB_LIGNES*sizeof(char)); for (i=0; i<NB_LIGNES; i++) { buffer[i] = (char*)malloc( sizeof(char) * TAILLE_LIGNE); } FILE *file = fopen(srcname,"r"); nbll = read_x_lines(file, buffer, x); i = 0; while(i<x) { nbprocs[i] = create_new_child(buffer[i], dstname);// ici j'ai mis buffer[i] mais je ne sais pas si la fonction va transmettre toute la ième ligne i++; } fclose(file); return nbprocs; } int main(int argc, char **argv) // argv[1] = n, argv[2] = fichier_source, argv[3] = fichier_destination { pid_t pid; int n = atoi(argv[1]); int *PID; PID = (int *) malloc(n*sizeof(int *)); PID = read_file_and_create_childs(argv[2], argv[3], n, PID); exit(0); }
J'ai un peu modifié le code car j'avais une erreur sur fopen, mais à présent c'est open qui passe pas.
Rectification : open passe, j'avais mal inclut fcntl.h
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define TAILLE_LIGNE 64 #define NB_LIGNES 60 // lit x lignes et les place dans le buffer int read_x_lines(FILE *file, char **buffer, int x) { int nb_lignes_lues = 0; int i=0; while((fgets(buffer[i],TAILLE_LIGNE,file))!= NULL && i<x) { nb_lignes_lues++; i++; } /* for(i=0;i<NB_LIGNES;i++) printf(" %s \n",buffer[i]);*/ return nb_lignes_lues; } // crée un fils en lui transmettant une chaine de caractère qu'il devra afficher et écrire dans le fichier "filename" int create_new_child(char *text, char *filename) { pid_t fils; printf(" Creation du fils \n"); fils = fork(); switch(fils) { case -1 : { perror(" fork "); exit(1); } case 0 : { printf(" %s \n",text); int fd; //FILE *fd; //if((fd=fopen(filename,"a")) == NULL); if((fd=open(filename,O_WRONLY | O_APPEND)) == -1) { perror(" fopen "); exit(1); } //if(fwrite(text,strlen(text), 1, fd) == 0) if(write(fd,text,strlen(text)) == -1) { perror(" write "); exit(1); } //fclose(fd); close(fd); exit(0); } default : { wait((int*)0); return fils; } } } int *read_file_and_create_childs(char *srcname, char *dstname, int x, int *nbprocs) { int i = 0; int nbll; char **buffer; buffer = (char **)malloc(NB_LIGNES*sizeof(char)); for (i=0; i<NB_LIGNES; i++) { buffer[i] = (char*)malloc( sizeof(char) * TAILLE_LIGNE); } FILE *file = fopen(srcname,"r"); nbll = read_x_lines(file, buffer, x); i = 0; while(i<x) { nbprocs[i] = create_new_child(buffer[i], dstname);// ici j'ai mis buffer[i] mais je ne sais pas si la fonction va transmettre toute la ième ligne i++; } fclose(file); return nbprocs; } int main(int argc, char **argv) // argv[1] = n, argv[2] = fichier_source, argv[3] = fichier_destination { pid_t pid; int n = atoi(argv[1]); int *PID; PID = (int *) malloc(n*sizeof(int *)); PID = read_file_and_create_childs(argv[2], argv[3], n, PID); exit(0); }
Et où est ton problème maintenant ?
Le probleme c'est que chaque processus devrait afficher (et écrire) x lignes, or je passe juste une chaine en argument à la fonction create_new_child, donc chaque ligne est écrite par un nouveau fils.
De plus je suis censé créer plusieurs fils, et connaitre l'ordre des fils créé, je ne vois vraiment pas comment un père peut ditinguer ces fils.
Effectivement, si on regarde ton code:
ça paraît normal !Code:nbprocs[i] = create_new_child(buffer[i], dstname);
Si tu veux que chaque processus fils écrive toutes les lignes, il te faut leur communiquer ces lignes:
et:Code:nbprocs[i] = create_new_child(buffer, x, dstname
Code:
1
2
3
4
5
6
7
8 int create_new_child(char **lignes, int nblignes, char *filename) { int nlig; ... for (nlig=0;nlig<nblignes;nlig++) { if(write(fd,lignes[nlig],strlen(lignes[nlig])) <0) {
J'ai pensé à faire cela, mais voyant que le protype de la fonction qui est suggerée dans l'énoncé est
J'ai pensé qu'il y avait une solution.Code:
1
2 int create_new_child(char *text, char *filename);
Une question que je me pose. Chaque fils est censé écrire x lignes.
Tel qu'est écrit ton code, tu envoies les mêmes x lignes à chaque fils.
Je suppose que ce n'est pas ce que tu veux.
Il te faut donc faire:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 int *read_file_and_create_childs(char *srcname, char *dstname, int x, int *nbprocs) { int i = 0; int nbll; char **buffer; buffer = (char **)malloc(x*sizeof(char *)); for (i=0; i<x; i++) { buffer[i] = (char*)malloc( sizeof(char) * TAILLE_LIGNE); } FILE *file = fopen(srcname,"r"); if (file == NULL) { ... } for (i=0;i<nbprocs;i++) { nbll = if (read_x_lines(file, buffer, x) != x) { ... } nbprocs[i] = create_new_child(buffer, x, dstname); } fclose(file); for (i=0;i<x;i++) free(buffer[i]); free(buffer); return nbprocs; }
Rectification par rapport à ton dernier message:
et:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 int *read_file_and_create_childs(char *srcname, char *dstname, int x, int *nbprocs) { int i = 0; int nbcars; char *texte; char **buffer; buffer = (char **)malloc(x*sizeof(char *)); for (i=0; i<x; i++) { buffer[i] = (char*)malloc( sizeof(char) * TAILLE_LIGNE); } FILE *file = fopen(srcname,"r"); if (file == NULL) { ... } for (i=0,nbcars=0;i<nbprocs;i++) { if (read_x_lines(file, buffer, x) != x) { ... } /* calcule le nombre de caractères contenus dans les x lignes */ for (nbcars=0,i=0;i<x;i++) { nbcars += strlen(buffer[i]); } /* construit un texte contenant les x lignes */ texte = (char *) malloc(nbcars*sizeof(char)+1); for (i=0,*texte=0;i<nbcars;i++) { strcat(texte,buffer[i]); free(buffer[i]); } nbprocs[i] = create_new_child(texte, dstname); free(texte); } fclose(file); free(buffer); return nbprocs; }
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 int create_new_child(char *text, char *filename) { pid_t fils; printf(" Creation du fils \n"); fils = fork(); switch(fils) { case -1 : { perror(" fork "); exit(1); } case 0 : { printf(" %s \n",text); int fd; //FILE *fd; if((fd=open(filename,O_WRONLY | O_APPEND)) <0) { ... } if(write(fd,text,strlen(text)) <0)