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 :

pipe, bloquant ? non bloquant ?


Sujet :

C

  1. #1
    Nouveau membre du Club Avatar de Butcher22
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2014
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2014
    Messages : 20
    Points : 36
    Points
    36
    Par défaut pipe, bloquant ? non bloquant ?
    Bonsoir,

    allons directement au but, voici deux bouts de codes


    Code : 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
     
    int main(int argc, char *argv[]) {
        int fds[2];
        int val;
        int res;
     
        assert(pipe(fds) != -1);
     
        switch (fork()) {
        case -1:
            exit(EXIT_FAILURE);
     
        case 0:
            printf("FILS\n");
            sleep(2);
            val = 123;
     
            /* on fait crasher */
            assert(0);
     
            assert(write(fds[1], &val, sizeof(unsigned int)) == sizeof(unsigned int));
            printf("val=%d\n", val);
            exit(EXIT_SUCCESS);
     
        default:
            printf("Attend que le fils envoie une information\n");
            res = read(fds[0], &val, sizeof(unsigned int));
            printf("read = %d, val = %d\n", res, val);
        }
     
        return 0;
    }
    Code : 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
    34
    35
    36
     
    int main(int argc, char *argv[]) {
        int fds[2];
        int val;
        int res;
     
        assert(pipe(fds) != -1);
     
        switch (fork()) {
        case -1:
            exit(EXIT_FAILURE);
     
        case 0:
            close(fds[0]);
     
            printf("FILS\n");
            sleep(2);
            val = 123;
     
            /* on fait crasher */
            assert(0);
     
            assert(write(fds[1], &val, sizeof(unsigned int)) == sizeof(unsigned int));
            printf("val=%d\n", val);
            exit(EXIT_SUCCESS);
     
        default:
            close(fds[1]);
     
            printf("Attend que le fils envoie une information\n");
            res = read(fds[0], &val, sizeof(unsigned int));
            printf("read = %d, val = %d\n", res, val);
        }
     
        return 0;
    }

    Je n'arrive pas à comprendre pourquoi dans la première V, le programme est bloqué, alors que dans la seconde non, que ce cache derrière la fermeture des extrémités non utilisées du pipe ???


    merci d'avance !

  2. #2
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Citation Envoyé par Butcher22 Voir le message
    Bonsoir,

    allons directement au but, voici deux bouts de codes
    ..........
    Je n'arrive pas à comprendre pourquoi dans la première V, le programme est bloqué, alors que dans la seconde non, que ce cache derrière la fermeture des extrémités non utilisées du pipe ???
    merci d'avance !
    Bonsoir
    Ce qui se cache en réalité est le comportement de read causer par assert.
    Je m’explique: L’appel de read est généralement bloquant. C’est-à-dire que le processus (dans le cas de votre exemple:cas 1) attend qu’il y ait des données à lire et si l’autre bout du tube est fermé, aucun processus ne possédera le tube ouvert en écriture et dans ce cas le read attend. C’est donc normal que vous obteniez ce comportement parce que d’une part le fils a été interrompue à cause de l’appel d'assert qui invoque indirectement abort terminant ainsi l'exécution du fils en le mettant celui-ci dans état zombie.
    Pourquoi le fils est il est dans un état zombie ?: Tout simplement parce qu'au moment où le processus fils s’est arrêté le système d’exploitation ne le fait pas disparaître, mais lui donne un état dit zombie c’est-à-dire qu’il ne tourne plus, mais qu’il reste dans la table de processus pour le faire disparaître il faut lire l’état de celui-ci avec les fonctions de la famille wait.
    Au final « read » est bloquant dans le processus père tant dit que le processus fils est dans l’état zombie. Voici ce qui se passe quand on effectue une petite investigation.

    Attention: le code source ci-dessous est susceptible de comporter des erreurs
    cependant, les instructions en bleu ont été implémenté pour appuyé ce dont j’ai énoncé


    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
    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
    ============================================================================
     Name        : Untitled.c
     Author      : SAMBIA39
     Version     : 0.1
     Copyright   : Copyright (c) 11/12/2016 SAMBIA39
     Description : Ansi-style
     ============================================================================
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <assert.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <signal.h>
    
    /*
    *	Purge zombie
    */
    void f_balayette_zombie( int sig ){
    	fprintf( stdout, "Zombie detécté...\n");
    	while ( 0 < waitpid(-1, NULL, WNOHANG));
    	fprintf( stdout, "Zombie Purger\n");
    	exit( EXIT_FAILURE );
    }
    
    int main(int argc, char *argv[]) {
    	
    	int fds[2];
    	int val;
    	int res;
    	
    	/*
    	*	Mise en place signal de 
            *      Détection de zombie
    	*	et activation de la purge
    	*/
    	struct sigaction sig_act;
    	memset(&sig_act, 0, sizeof(sig_act));
    	sig_act.sa_flags = 0;
    	sigemptyset( &(sig_act.sa_mask) );
    	sig_act.sa_handler = f_balayette_zombie;
    	if( 0 != sigaction(SIGCHLD, &sig_act, NULL) ){
    		fprintf( stderr, "Erreur signal\n" );
    		exit( EXIT_FAILURE );
    	}
     
    	assert(pipe(fds) != -1);
     
    	switch (fork()) {
    	case -1:
    		exit(EXIT_FAILURE);
     
    	case 0:
    		printf("FILS\n");
    		sleep(2);
    		val = 123;
     
    		/* on fait crasher */
    		assert(0);
    
    		assert(write(fds[1], &val, sizeof(unsigned int)) == sizeof(unsigned int));
    		printf("val=%d\n", val);
    		exit(EXIT_SUCCESS);
     
    	default:
    		printf("Attend que le fils envoie une information\n");
    		res = read(fds[0], &val, sizeof(unsigned int));
    		printf("read = %d, val = %d\n", res, val);
    	}
     
    	return 0;
    }

    Dans l’autre cas vous avez fermé le tube en écriture et comme cela ne sert plus à grand-chose (un read sur un tube fermé en écriture) "read" renvoie alors zéro plutôt qu’être bloquant. Cela permet au processus de lecture de détecter l’équivalent tube d’une fin de fichier (EOF). Cependant, tout comme dans le premier cas vous avez le fils qui passe dans l’état zombie à cause de l’appel de la fonction « assert ».

    A l’avenir si vous utiliser les processus assurée-vous d’avoir un mécanisme dit balayette zombie qui permet de son débarrasseur.
    Quant à assert, il doit uniquement être utilisé à des fins de débogage de programme, et donc dans votre cas deux, si vous enlevé votre macro assert («#define NDEBUG 1» avant qu'il lise le fichier d'en-tête «assert.h».)
Le programme fonctionnera correctement.
    (Pour rendre le read ou write non bloquant il faut utiliser la fonction "fctnl" sur le descripteur de votre tube avec les options comme O_NONBLOCK et O_ASYNC par exemple)

    à bientôt
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

Discussions similaires

  1. Pipe non bloquant
    Par Eagles dans le forum Langage
    Réponses: 3
    Dernier message: 28/01/2010, 13h45
  2. Lecture d'un pipe de façon non-bloquante
    Par Premium dans le forum POSIX
    Réponses: 6
    Dernier message: 31/05/2006, 09h02
  3. Réponses: 6
    Dernier message: 05/01/2006, 21h09
  4. Réponses: 3
    Dernier message: 16/03/2004, 16h42
  5. [API] Communication série NON-bloquante : OVERLAPPED/Thread
    Par Rodrigue dans le forum C++Builder
    Réponses: 2
    Dernier message: 07/11/2003, 13h43

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