Bonjour à tous,
C'est encore moi avec un nouveau problème qui concerne toujours les processus UNIX en C… !
Contexte
Comme l'indique le titre, je dois faire un petit programme qui affiche x fois un certain caractère, avec un délai d'affichage pour ce caractère de y secondes. En fait, ce programme doit faire cela pour plusieurs caractères (si ce n'est pas clair, vous comprendrez en jetant un coup d'oeil à l'exemple qui suit). L'affichage de chaque caractère est à faire en parallèle aux autres affichages (donc le programme est multi-processus).
On passe à ce programme un fichier contenant le caractère à taper, le x et le y. Ce fichier est le suivant :
1 2 | a 4 2 b 2 1 |
Ainsi ce fichier indique au programme d'afficher 'a' 4 fois toutes les 2 secondes, et 'b' 2 fois toutes les 1 seconde, et ce en parallèle.
Le programme est multi-processus : ici, le processus-fils-1 s'occupe du 'a', et le processus-fils-2 s'occupe du 'b'.
Ma question
J'ai écrit un code que vous trouverez en fin de message. Celui-ci compile, et s'exécute sans problème mais ne fait pas ce qu'il est censé faire. En effet, ce programme, en lui passant le fichier que je vous ai donné tout à l'heure, ne fait qu'afficher 'bb' après de plusieurs secondes d'attente. Et par ailleurs, si je mets le délai de 'b' à 1, j'attendrai 1 seconde, à 2, 2 secondes. Mais à 3, j'attendrai 5 secondes, etc. Je trouve ça étrange.
Je ne comprends pas du tout d'où le problème peut venir…
Ma solution
Le bug viendrait du sleep
. En effet, sans celui-ci, les processus-enfants sont tous bien créés, et tous les caractères sont affichés (mais ils ne sont pas mélangés puisqu'il n'y a pas de délai). En revanche, avec le sleep
, seul le processus du 'b' est lancé et il n'y a pas de délai entre les deux 'b' =/
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 | #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <string.h> int main(int argc, char* argv[]) { pid_t pid; FILE* file = fopen(argv[1], "r"); if(file == NULL) { perror("Open"); exit(EXIT_FAILURE); } // <!-- The following vars are used for the reading of the file --> char current_char = 0; char char_to_print; // ie. : the first file's column char buffer_number_of_prints[592] = {0}; // ie. : the snd file's column int i1 = 0; // Will be used to write in the previous buffer char buffer_delay[592] = {0}; // ie. : the thd (and last) file's column int i2 = 0; int flag_column = 0; // 0 = first file's column, 1 = snd one, 2 = last one (precision : two columns are separated by a space) // <!-- ### --> while(current_char != EOF) { current_char = (char) fgetc(file); if(current_char != ' ') { // So current_char is : the char to type XOR The number of times XOR The delay XOR \n if(current_char == '\n' || current_char == EOF) { // So we just read an entire line of the file : we have valued the var "char_to_print" + the 2 buffers pid = fork(); // A new process is created and will do its job if(pid != 0) { // So we just read an entire line + we are the parent process, SO : we re-init all the vars and we're going to read the next file's line flag_column = 0; memset(buffer_number_of_prints, 0, 592); i1 = 0; memset(buffer_delay, 0, 592); i2 = 0; continue; // We're going to read the next file's line } else { // If the current process is a child, it has to do its job (ie. : printing the typed char with x delay and y times) int i = 0; int max = atoi(buffer_number_of_prints); int del = atoi(buffer_delay); // These two buffers have been filed by the parent process for(; i < max; i++) { fprintf(stdout, "%i%c ", getpid(), char_to_print); sleep(del); } return 0; // The process ended its job so we stop it } } // If we are the parent process (the child ones have been stopped previously thanks to the instruction `return 0`), we fill the var `char_to_print` and the two buffers according to the value of the var `flag_column` if(flag_column == 0) { char_to_print = current_char; } else if(flag_column == 1) { buffer_number_of_prints[i1] = current_char; i1++; } else if(flag_column == 2) { buffer_delay[i2] = current_char; i2++; } } else { // If we encounter a space in the reading of the file, it means we are changing of column : so we increment this var flag_column++; } } // The parent process closes the file's stream if(fclose(file) != 0) { perror("Close"); exit(EXIT_FAILURE); } // Before ending, the parent process wait for its children ones wait(NULL); return 0; } |
Voilà je vous remercie d'avance et vous souhaite une bonne journée !