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 :

pthread_setspecific && _getspecific


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2009
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 62
    Par défaut pthread_setspecific && _getspecific
    Bonsoir,

    J'ai voulu utiliser les fonctions pthread_setspecific() et pthread_getspecific() afin de pouvoir transférer des données d'un thread à un autre, mais je n'arrive pas à les utiliser, je crée deux thread, l'un dans lequel je place les données avec pthread_setspecific() et l'autre dans lequel je tente de les récupérer, seulement il me retourne toujours 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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
     
    void * fonction (void * arg);
     
    pthread_key_t	key;
     
    int main(){
    	pthread_t 	pth;
    	int 		i;
     
    	pthread_key_create(& key, free);
    	for(i = 0; i < 2; i++){
    		if(pthread_create(& pth, NULL, fonction, (void *) i) != 0){
    			perror("pthread_create");
    			exit(EXIT_FAILURE);
    		}
    	}
    	/*	Processus père		*/
     
    	while(1)	sleep(1);
    }
     
    void * fonction(void * arg){
    	int		i = (int)arg;
    	int		j = 4;
    	int		data;
     
    	switch(i){
    		case 0:
    			while(1){
    				pthread_setspecific(key, j);
    				sleep(1);
    			}
    			break;
    		case 1:
     
    			while(1){
    				data = (int)pthread_getspecific(key);
    				printf("data = %d\n", data);
    				sleep(1);
    			}
    			break;
    	}
     
    	pthread_exit(NULL);
    }
    En utilisant pthread_getspecific() dans le même thread que celui ou j'utilise pthread_setspecific(), ca marche sans problème, mais je vois plus tellement l'intérêt..

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Plutôt que de faire un while(1) sleep(1);
    Pour attendre la fin de l'exécution d'un thread fils :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int pthread_join(pthread_t th, void **thread_return);
    http://www.linux-kheops.com/doc/man/...ad_join.3.html

    Ensuite,
    Ca c'est très moche sachant que i est un int et qu'un int n'a pas toujours la même taille qu'une adresse.

    De plus, tu essaye de lire et de traiter des informations sans même savoir si tu as écris ou pas, et en plus, tu fais des hypothèses sur la vitesse d'exécutions avec tes sleep(1).
    Il faut utiliser un mutex :
    http://www.linux-kheops.com/doc/man/...ex_init.3.html

    Sinon, RTFM!
    http://manpagesfr.free.fr/man/man3/p..._create.3.html
    Chaque thread possède un segment mémoire privé, le TSD (Thred-Specific Data : Données Spécifiques au Thread).
    [...]
    pthread_key_create() alloue une nouvelle clé TSD.
    Je pense que tu t'es trompé de fonctions.

    Pour faire ce que tu veux faire, plusieurs possibilités :
    Créer une structure et transmettre son adresse.
    Créer un tube.
    Créer une liste (ou file ou pile) chaînées chaque maillon contenant un pointeur vers une valeur, la taille de la valeur et un pointeur vers le maillon suivant.
    /!\ ne pas oublier les Mutex.

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2009
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 62
    Par défaut
    Plutôt que de faire un while(1) sleep(1);
    Pour attendre la fin de l'exécution d'un thread fils :

    int pthread_join(pthread_t th, void **thread_return);
    Comment faire pour attendre que tous les threads fils soit terminés et non pas un spécifique ?

    (void *) i
    Ca c'est très moche sachant que i est un int et qu'un int n'a pas toujours la même taille qu'une adresse.
    Il faut que i soit un pointeur donc ?



    A vrai dire, j'ai croisé ces fonctions dans un bouquin mais elles n'etaient pas vraiment détaillées, j'ai voulu essayer de les utiliser sans succès, et malheureusement il n'y a pas beaucoup de lien à ce sujet sur la toile.

    J'ai tenté de changer le code, mais ça ne marche toujours pas, j'ai droit a une erreur de segmentation maintenant:

    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
    71
    72
    73
    74
    75
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
     
    void * fonction (void * arg);
     
    struct test{
    	int j;
    };
     
    pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
     
    pthread_key_t	key;
     
    int main(){
    	pthread_t 	pth;
    	int 		i;
     
    	pthread_key_create(& key, free);
    	for(i = 0; i < 2; i++){
    		if(pthread_create(& pth, NULL, fonction, (void *) i) != 0){
    			perror("pthread_create");
    			exit(EXIT_FAILURE);
    		}
    	}
     
    	/*	Processus père		*/
    	pthread_join(pth, NULL);
     
    	printf("Fermeture du processus père...\n");
    	pthread_mutex_destroy(& mutex);
     
    	pthread_exit(NULL);
     
    }
     
    void * fonction(void * arg){
    	int		i = (int)arg;
    	struct test*	test;	
    	struct test*	data;
     
     
    	test->j = 5;
     
    	switch(i){
    		case 0:
    			pthread_mutex_lock(& mutex);
    			printf("0-Mutex vérrouillé\n");
     
    			if(pthread_setspecific(key, (void *) test) != 0){
    				perror("pthread_setspecific");
    				pthread_mutex_unlock(& mutex);
    				exit(EXIT_FAILURE);
    			}
     
    			pthread_mutex_unlock(& mutex);
    			printf("0-Mutex dévérrouillé\n");
     
    			pthread_exit(NULL);
    			break;
    		case 1:
    			pthread_mutex_lock(& mutex);
    			printf("1-Mutex vérrouillé\n");
     
    			data = (struct test*)pthread_getspecific(key);
    			printf("data->j = %d\n", data->j);
     
    			pthread_mutex_unlock(& mutex);
    			printf("1-Mutex dévérrouillé\n");
     
    			pthread_exit(NULL);
    			break;
    	}
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    0-Mutex vérrouillé
    0-Mutex dévérrouillé
    Erreur de segmentation

  4. #4
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Citation Envoyé par Arkenis Voir le message
    Comment faire pour attendre que tous les threads fils soit terminés et non pas un spécifique ?
    En mettant NULL, on peut attendre un seul thread (n'importe lequel)
    Ensuite, je ne suis pas sûr, mais cette fonction doit renvoyer quelque chose lorsqu'il n'y a plus aucun thread à attendre. Il suffit donc de faire une boucle while.

    Citation Envoyé par Arkenis Voir le message
    Il faut que i soit un pointeur donc ?
    Oui mais attention, si tu modifie *i, il sera aussi modifié pour les autres.
    Ici, plutôt que de faire une seule fonction puis de faire un grand if/else, je pense qu'il vaut mieux lancer deux fonctions.
    Sinon il faudrait passer un pointeur sur un char[2] et incrémenter ce pointeur à chaque tour de boucle.
    Chaque processus lisant son id par *(car *)data;


    Citation Envoyé par Arkenis Voir le message
    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
    71
    72
    73
    74
    75
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
     
    void * fonction (void * arg);
     
    struct test{
    	int j;
    };
     
    pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
     
    pthread_key_t	key;
     
    int main(){
    	pthread_t 	pth;
    	int 		i;
     
    	pthread_key_create(& key, free);
    	for(i = 0; i < 2; i++){
    		if(pthread_create(& pth, NULL, fonction, (void *) i) != 0){
    			perror("pthread_create");
    			exit(EXIT_FAILURE);
    		}
    	}
     
    	/*	Processus père		*/
    	pthread_join(pth, NULL);
     
    	printf("Fermeture du processus père...\n");
    	pthread_mutex_destroy(& mutex);
     
    	pthread_exit(NULL);
     
    }
     
    void * fonction(void * arg){
    	int		i = (int)arg;
    	struct test*	test;	
    	struct test*	data;
     
     
    	test->j = 5;
     
    	switch(i){
    		case 0:
    			pthread_mutex_lock(& mutex);
    			printf("0-Mutex vérrouillé\n");
     
    			if(pthread_setspecific(key, (void *) test) != 0){
    				perror("pthread_setspecific");
    				pthread_mutex_unlock(& mutex);
    				exit(EXIT_FAILURE);
    			}
     
    			pthread_mutex_unlock(& mutex);
    			printf("0-Mutex dévérrouillé\n");
     
    			pthread_exit(NULL);
    			break;
    		case 1:
    			pthread_mutex_lock(& mutex);
    			printf("1-Mutex vérrouillé\n");
     
    			data = (struct test*)pthread_getspecific(key);
    			printf("data->j = %d\n", data->j);
     
    			pthread_mutex_unlock(& mutex);
    			printf("1-Mutex dévérrouillé\n");
     
    			pthread_exit(NULL);
    			break;
    	}
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    0-Mutex vérrouillé
    0-Mutex dévérrouillé
    Erreur de segmentation
    Tu as un segmentation fault car pthread_getspecific(key); va renvoyer NULL.
    Tu n'as pas lu ce que je t'ai passé^^
    les fonctions que tu utilises permettent d'utiliser des variables dans un espace mémoire réservé et accessible uniquement par le thread ayant créé la clé. Ceci ne sert absolument pas à partager des variables entre les threads.

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2009
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 62
    Par défaut
    Tu as un segmentation fault car pthread_getspecific(key); va renvoyer NULL.
    Tu n'as pas lu ce que je t'ai passé^^
    les fonctions que tu utilises permettent d'utiliser des variables dans un espace mémoire réservé et accessible uniquement par le thread ayant créé la clé. Ceci ne sert absolument pas à partager des variables entre les threads.
    Si si je les ai lu :-) Mais je pensais que si l'erreur était a la ligne du getspecific, le printf("1-Mutex vérrouillé\n"); s'éxécuterais, or ce n'est pas le cas, et je pensais aussi que si l'écriture(qui elle est testée) fonctionnait, la lecture fonctionnerais aussi.

    J'ai mal compris leur principe je crois bien, pour moi la fonction pthread_key_create() alloue un espace mémoire qui ne soit pas accessible juste par le thread, en fait si les données restent utilisables juste par le thread qui a invoqué la fonction je vois vraiment pas l'intérêt ><

  6. #6
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Ceci sert à faire des variables globales (pouah! pas beau) spécifiques à un thread.

    Pour ce que tu veux faire, j'avais fait une pile d'éléments pouvant contenir tout et n'importe quoi.

    En l'adaptant, tu pourras refaire ce que tu essayais de faire avec le pthread_key

    Bon, je l'ai fait au début de l'année donc ça date un peu et je ne garantie pas qu'il y ai 2/3 trucs horribles

    Au pire tu auras une idée de comment tu pourrais faire.


    Passer par une méthode comme celle-ci permet de se passer d'un tube qui serait assez lourd, mais il faut faire attention aux Mutex!

    Sinon, il faut faire une structure dont tu passeras un pointeur.
    Fichiers attachés Fichiers attachés
    • Type de fichier : c pile.c (3,1 Ko, 76 affichages)
    • Type de fichier : h pile.h (623 octets, 66 affichages)
    • Type de fichier : c test.c (2,2 Ko, 55 affichages)

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

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