IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

fflush et '\n'


Sujet :

C

  1. #1
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut fflush et '\n'
    Bonjour à tous

    Je me suis trouvé récemment confronté à un souci miniime. En effet, j'ai remarqué que dans le fichier contenant les logs de mon serveur, les lignes étaient toutes rangées par serveur (le serveur est lancé par xinetd donc il peut y en avoir plusieurs qui tournent en même temps).
    Mais le serveur écrit plusieurs lignes de log. Et chaque ligne est terminée par '\n'. Et j'étais jusqu'à présent persuadé que le '\n' activait un fflush() (en tout cas, c'est comme ça quand on écrit dans stdout). Donc dans le log qui contient toutes les lignes, ces lignes auraient dû être rangées en fonction du moment où elles sont écrites et non en fonction de qui les écrit.
    J'en suis arrivé à la conclusion que le '\n' n'active pas de fflush(). Donc les lignes sont écrites physiquement au moment où le serveur se termine et qu'il ferme le log.

    Pour vérifier, j'ai créé un petit code de test...

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/wait.h>
     
    void fils(FILE *fp, int n) {
    	int i;
    	for (i=0; i < 5; i++) {
    		fprintf(fp, "pid=%d écriture fils %d (%d)\n", getpid(), n, i);
    		//fflush(fp);
    		sleep(n);
    	}
    }
     
    int main() {
    	FILE *fp=NULL;
    	int i;
    	unlink("toto");
    	fp=fopen("toto", "a");
     
    	for (i=1; i <= 3; i++) {
    		printf("Fils %d\n", i);
    		if (fork() == 0) {
    			fils(fp, i);
    			exit(0);
    		}
    	}
    	while (wait(NULL) != -1);
    	fclose(fp);
    	printf("ok\n");
     
    	return 0;
    }

    Voià. Je crée 3 fils. Chaque fils écrit à son rythme dans un seul et unique log. Or, au final, le fichier de log "toto" contient les lignes rangées par n° de fils et non rangées par ordre d'écriture. Mais si maintenant on décommente le fflush(fp), là les lignes arrivent dans le log rangées par ordre d'écriture.

    Et le résultat est le même si, au lieu d'ouvrir le fichier dans le père, je l'ouvre dans chaque fils...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/wait.h>
     
    void fils(FILE *fp, int n) {
    	fp=fopen("toto", "a");
    	int i;
    	for (i=0; i < 5; i++) {
    		fprintf(fp, "pid=%d écriture fils %d (%d)\n", getpid(), n, i);
    		//fflush(fp);
    		sleep(n);
    	}
    	fclose(fp);
    }
     
    int main() {
    	FILE *fp=NULL;
    	int i;
    	unlink("toto");
     
    	for (i=1; i <= 3; i++) {
    		printf("Fils %d\n", i);
    		if (fork() == 0) {
    			fils(fp, i);
    			exit(0);
    		}
    	}
    	while (wait(NULL) != -1);
    	printf("ok\n");
     
    	return 0;
    }

    Donc il semblerait bien que le '\n' n'active pas forcéement un fflush(). Toutefois, on m'a toujours conseillé de le mettre pour stdout (et maintenant moi aussi je le conseille aux autres). Donc il semblerait que '\n" active le fflush() quand ça concerne spécifiquement stdout.

    Pour vérifier ce dernier détail, je remplace alors fils(fp, i) par fils(stdout, i) et là effectivement, que le fflush() soit activé ou pas, les lignes apparaissent à l'écran dans l'ordre d'écriture.

    Si quelqu'un avait un avis à ce propos...

    Merci à tous. Heureux si je peux vous intéresser à ce nouveau challenge...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Je vais pas faire avancer le schmilblick mais j'ai justement toujours entendu l'inverse : \n ne déclenche pas de flush. Il faut toujours le faire manuellement.
    Ce qui m'a toujours semblé logique, si je veux écrire plusieurs lignes, ce serait chiant qu'il flush chaque ligne.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Je vais pas faire avancer le schmilblick
    En effet
    Mais au moins tu sais l'écrire ce con de mot

    Citation Envoyé par Bousk Voir le message
    Ce qui m'a toujours semblé logique, si je veux écrire plusieurs lignes, ce serait chiant qu'il flush chaque ligne.
    C'est vrai que d'un point de vue logique tu marques un point. Pour un fichier, peut-être que le fflush ne se justifie pas (écriture disque inutile). Peut-être alors que ce n'est activé que pour stdout (parce que ça l'est réellement pour stdout. Par exemple: printf("Hello"); sleep(10); printf("Word\n") te donne toute la phrase à l'écran d'un coup mais au bout de 10sec tandis que si tu rajoutes un '\n' au "Hello" il arrive immédiatement avant le sleep(10))...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Je dirais qu'au-delà du fait que c'est à la discrétion du système, ça dépend de ce à quoi est « branché » stdout. Si c'est un tty alors le newline est susceptible d'entraîner un flush, autrement non. Il y a pas mal de commandes qui passent ou non en mode interactif selon la configuration d'invocation (mais j'ai pas d'exemple en tête là, de suite).

Discussions similaires

  1. utiliser fflush() ?
    Par isoman dans le forum C
    Réponses: 4
    Dernier message: 14/12/2006, 09h11
  2. fflush() sur un pipe ?
    Par shuygar dans le forum POSIX
    Réponses: 4
    Dernier message: 07/08/2006, 02h49
  3. fflush
    Par ggnore dans le forum C
    Réponses: 3
    Dernier message: 06/01/2005, 17h58
  4. fflush(stdin)
    Par lestat dans le forum C
    Réponses: 9
    Dernier message: 23/03/2004, 11h46
  5. fflush(stdin)
    Par BURZUM dans le forum C
    Réponses: 2
    Dernier message: 06/01/2004, 10h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo