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 :

utiliser des threads au lieu des forks


Sujet :

C

  1. #1
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 45
    Points : 34
    Points
    34
    Par défaut utiliser des threads au lieu des forks
    Est-il possible d'utiliser des pthread au lieu d'un fork, pour le code suivant ?

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    #include <stdio.h>
      #include <memory.h>
      #include <unistd.h>
     
      int main( int argc, char ** argv )
      {
       /* create the pipe */
       int pfd[2];
       if (pipe(pfd) == -1)
         {
           printf("pipe failed\n");
           return 1;
         }
     
       /* create the child */
       int pid;
       if ((pid = fork()) < 0)
         {
           printf("fork failed\n");
           return 2;
         }
     
       if (pid == 0)
         {
           /* child */
           close(pfd[1]); /* close the unused write side */
           dup2(pfd[0], 0); /* connect the read side with stdin */
           close(pfd[0]); /* close the read side */
           /* execute the process (wc command) */
           execlp("wc", "wc", (char *) 0);
           printf("wc failed"); /* if execlp returns, it's an error */
           return 3;
         }
       else
         {
           /* parent */
           close(pfd[0]); /* close the unused read side */
           dup2(pfd[1], 1); /* connect the write side with stdout */
           close(pfd[1]); /* close the write side */
           /* execute the process (ls command) */
           execlp("ls", "ls", (char *)0);
           printf("ls failed"); /* if execlp returns, it's an error */
           return 4;
         }
       return 0;
      }
    J'ai essayé, en mettant les flux en argument. Mais lorsque je ferme l'écriture ou la lecture d'un flux dans un thread, cela le ferme aussi pour l'autre thread...
    Donc cela ne fonctionne pas.

    Comment peut-on faire?

  2. #2
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Points : 7 163
    Points
    7 163
    Par défaut
    Tu peux sans problème utiliser des threads au lieu de processus séparés.
    Par contre, tu ne dois pas fermer la lecture pour l'émetteur et l'écriture pour le lecteur avant de commencer puisque le tableau à 2 descripteurs est partagé par les 2 threads. Globalement, tu n'as plus deux tableaux mais un seul, partagé.

    Ton problème vient probablement du manque de compréhension sur le fork : ton tableau de descripteurs est dupliqué dans les 2 processus. Chaque processus possède un tableau à 2 descripteurs, un seul descripteur sera utile pour chaque processus. Celui qui est inutile est fermé.
    Par contre, dans l'usage des threads, tu as un seul processus, un seul tableau à 2 descripteurs. Les 2 threads accèdent aux 2 descripteurs. Il n'y a aucun descripteur inutile.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  3. #3
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 45
    Points : 34
    Points
    34
    Par défaut
    Ok mais cela ne fonctionne pas.

    Voici ma transformation :
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    #include <stdio.h>
    #include <memory.h>
    #include <unistd.h>
    #include <pthread.h>
     
    void * child(void * pfds) {
    	int * pfd = pfds;
     
    	//close(pfd[1]); /* close the unused write side */
    	dup2(pfd[0], 0); /* connect the read side with stdin */
    	//close(pfd[0]); /* close the read side */
    	/* execute the process (wc command) */
    	execlp("wc", "wc", (char *) 0);
    	printf("wc failed"); /* if execlp returns, it's an error */
    }
     
    void * parent(void * pfds) {
    	int * pfd = pfds;
     
    	//close(pfd[0]); /* close the unused read side */
    	dup2(pfd[1], 1); /* connect the write side with stdout */
    	//close(pfd[1]); /* close the write side */
    	/* execute the process (ls command) */
    	execlp("ls", "ls", (char *)0);
    	printf("ls failed"); /* if execlp returns, it's an error */
    }
     
    int main( int argc, char ** argv )
    {
    	/* create the pipe */
    	int pfd[2];
    	if (pipe(pfd) == -1)
    	{
    		printf("pipe failed\n");
    		return 1;
    	}
     
    	pthread_t t1, t2;
    	pthread_create(&t1, NULL, child, pfd);
    	pthread_create(&t2, NULL, parent, pfd);
     
    	pthread_join(t1, NULL);
    	pthread_join(t2, NULL);
     
    	return 0;
    }
    Rien ne s'affiche....

  4. #4
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Points : 7 163
    Points
    7 163
    Par défaut
    execlp remplace le processus courant. Tu ne peux pas l'utiliser dans ce cas puisque tu veux que ton programme courant se termine.
    Tu devrais utiliser popen. Mais du coup le tableau de descripteur devient inutile.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  5. #5
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 45
    Points : 34
    Points
    34
    Par défaut
    Je n'ai pas très bien compris.


    Tu ne peux pas l'utiliser dans ce cas puisque tu veux que ton programme courant se termine.
    Pourquoi, je ne peux pas utiliser execlp ?
    Et pourquoi mon programme ne se terminerait pas ?

  6. #6
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Points : 7 163
    Points
    7 163
    Par défaut
    Va lire la documentation sur execlp.
    Pour résumé très brièvement, execlp remplace le processus courant par un autre processus construit depuis ses arguments. Ton programme est remplacer par "wc" ou par "ls", selon le thread le plus rapide.
    Dans ton programme multi-thread, tu ne peux pas utiliser execlp.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  7. #7
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Points : 28 119
    Points
    28 119
    Par défaut
    Bonjour,

    Dans ton programme, tu cherches a executer deux programmes externes, wc et ls. Ceux-ci doivent etre lances dans des processus distincts du tient. Apres, la question qui se pose est de savoir si ton programme doit lui-meme se dupliquer ou non pour lancer ces processus externes : non, il n'est pas obligé de le faire.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  8. #8
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 45
    Points : 34
    Points
    34
    Par défaut
    Ok je comprend.

    Par contre, imaginons que nous avons :
    - une méthode transfert() qui lit sur son entrée standard une chaine de caractère et qui affiche sur sa sortie standard une autre chaine.

    Et que l'on veut :
    - dans un thread, envoyer une chaine de caractere sur l'entrée de transfert()
    - dans un autre thread, récupérer la chaine de sortie de transfert()

    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
    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
     
    #include <stdio.h>
    #include <memory.h>
    #include <unistd.h>
    #include <pthread.h>
     
    typedef struct {
    	int * p1;
    	int * p2;
    } pipes;
     
    void * ecrire(void * pfds) {
    	int * pfd = pfds;
     
    	write(pfd[1], "coucou\n", strlen("coucou\n"));
    }
     
    void * transfert(void * pfds) {
    	pipes * pfd = pfds;
     
    	dup2(pfd->p1[0], 0);
    	dup2(pfd->p2[1], 1);
     
    	char saisie[20];
    	fgets (saisie, sizeof saisie, stdin);
    	strcat(saisie, " retour");
    	printf("%s", saisie);
    }
     
    void * lire(void * pfds) {
    	int * pfd = pfds;
     
    	char * buffer = malloc(sizeof(char)*14);
    	read(pfd[0], buffer, sizeof(buffer));
     
    	printf("%s",buffer);
    	free(buffer);
    }
     
    int main( int argc, char ** argv )
    {
    	int pfd1[2];
    	int pfd2[2];
    	if (pipe(pfd1) == -1)
    	{
    		printf("pipe failed\n");
    		return 1;
    	}
    	if (pipe(pfd2) == -1)
    	{
    		printf("pipe failed\n");
    		return 1;
    	}
     
    	pthread_t t1, t2, t3;
    	pthread_create(&t1, NULL, ecrire, pfd1);
     
    	pipes * pfd12 = malloc(sizeof(pipes));
    	pfd12->p1 = pfd1;
    	pfd12->p2 = pfd2;
    	pthread_create(&t2, NULL, transfert, pfd12);
     
    	pthread_create(&t3, NULL, lire, pfd2);
     
    	pthread_join(t1, NULL);
    	pthread_join(t2, NULL);
    	pthread_join(t3, NULL);
     
    	return 0;
    }
    Cela ne fonctionne pas, pourquoi ?

  9. #9
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Points : 7 163
    Points
    7 163
    Par défaut
    Il n'y a pas à dupliquer les descripteurs via dup2 pour écraser l'entrée et la sortie standard. Reste sur les fonction read et write, c'est bien plus simple.
    Voici un code qui fonctionne :

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    #include <stdio.h>
    #include <memory.h>
    #include <unistd.h>
    #include <pthread.h>
     
    void * ecrire( void * p_descripteur )
    {
            int * descripteur = p_descripteur;
            write( * descripteur, "coucou\n", strlen( "coucou\n" ) );
            close( * descripteur );
    }
     
    void * transfert(void * tab_descripteur)
    {
            int * tab = tab_descripteur;
            char saisie[ 20 ];
     
            read( tab[ 0 ], saisie, sizeof( saisie ) );
            close( tab[ 0 ] );
            strncat( saisie, " retour\n", 20 );
            saisie[ 19 ] = NULL; //terminer la chaine si le cat precedent n'avait pas assez de place
            write( tab[ 1 ], saisie, strlen( saisie ) );
            close( tab[ 1 ] );
    }
     
    void * lire( void * p_descripteur )
    {
            char buffer[ 20 ];
            read( * ((int*)p_descripteur), buffer, sizeof( buffer ) );
            buffer[ 19 ] = NULL;
            close( * ((int*)p_descripteur) );
     
            printf( "lire: %s", buffer );
    }
     
    int main()
    {
            int pfd1[2];
            int pfd2[2];
            if( pipe( pfd1 ) == -1 ) { printf( "pipe failed\n" ); return 1; }
            if( pipe( pfd2 ) == -1 ) { printf( "pipe failed\n" ); return 1; }
     
            pthread_t t1, t2, t3;
            pthread_create( & t1, NULL, ecrire, & pfd1[ 1 ] );
     
            int pfd_transfert[ 2 ];
            pfd_transfert[ 0 ] = pfd1[ 0 ];
            pfd_transfert[ 1 ] = pfd2[ 1 ];
            pthread_create( & t2, NULL, transfert, pfd_transfert );
     
            pthread_create( & t3, NULL, lire, & pfd2[ 0 ] );
     
            pthread_join( t1, NULL );
            pthread_join( t2, NULL );
            pthread_join( t3, NULL );
     
            return 0;
    }
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  10. #10
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 45
    Points : 34
    Points
    34
    Par défaut
    Ok merci !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utiliser un tableau au lieu des frames
    Par dekalima dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 06/01/2011, 10h55
  2. Comment avoir des matrices au lieu des vecteurs
    Par HOLLY dans le forum MATLAB
    Réponses: 8
    Dernier message: 22/07/2008, 17h30
  3. le formulaire renvoi des 00 au lieu des champs saisi
    Par mademoizel dans le forum ASP
    Réponses: 4
    Dernier message: 23/01/2008, 14h32
  4. Utiliser des procédures au lieu des classes
    Par ahage4x4 dans le forum ASP
    Réponses: 5
    Dernier message: 29/06/2005, 10h53

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