• STATISTIQUES
  • Il y a eu un total de 1 membres et 918 visiteurs sur le site dans les dernières 24h pour un total de 919 personnes!


    Membres: 2 097
    Discussions: 3 554
    Messages: 32 736
    Tutoriels: 78
    Téléchargements: 38
    Sites dans l'annuaire: 58


  • ANNUAIRE
  • [FR] Asp-php
    Tutoriaux sur ASP, PHP, ASP.net, XML, SQL, Javascript, HTML, VML - Scripts et ressources pour webmasters - Forums d&#...
    Programmation
    [EN] hax.tor
    50 level de challenges mélangés
    Challenges
    [FR] PHP France
    Pour tout savoir sur le PHP, en français. Vous trouverez des tutoriels, des exemples, des astuces, toute la do...
    Hacking
    [FR] dcode
    dcode.fr est le site indispensable pour décoder des messages, tricher aux jeux de lettres, résoudre des énigmes...
    Outils / Add-on
    [FR] Hackfest
    Le Hackfest est un évènement de sécurité et de piratage informatique au Québec reg...
    Hacking
    [EN] Reddit
    Subreddit dédié à la sécurité informatique.
    Hacking
    [EN] social-engineer
    Site dédié au Social Engineering en général.
    Hacking

  • DONATION
  • Si vous avez trouvé ce site internet utile, nous vous invitons à nous faire un don du montant de votre choix via Paypal. Ce don servira à financer notre hébergement.

    MERCI!




[C] Multiples arguments pour une fonction appelée dans un Thread

Bonjour.

0001: Introduction
Suite à mon tuto sur les threads en C, je me lance dans une suite logique. Celui-ci parlera de "comment passer plusieurs arguments à une fonction étant appelée dans un thread". En effet si on reprend correctement le tuto précédent, on peut s'apercevoir que lors de la création d'un thread, on ne peut passer qu'un seul argument. Mais certaines fois, nous aurons besoin de plusieurs arguments. Pour pouvoir "comprendre" la démarche il vous faudra un minimum de connaissances dans les structures, car c'est grâce à celles-ci que nous pourrons résoudre le problème.

aller c'est tipar Wink

0010: Bref rappel

Lors du tuto précédent, j'ai parlé de certaines fonctions que la lib pthread contient. C'est pourquoi je ne m'atarderais pas sur celle-ci. En revanche afin de bien comprendre la manière de procéder je reviendrai quand même sur pthread_create()

Donc comme vu précédement, après avoir déclaré votre thread à l'aide de pthread_t:
Code C :

pthread_t thread;
 


nous faisons appel à pthread_create() dont voici le prototype:
Code C :

int pthread_create (pthread_t * thread, pthread_attr_t * attr, void * (* start_routine) (void *), void * arg);
 


pthread_t thread: Ici c'est le nom de votre thread que l'on verra un peu plus tard, déclaré.
pthread_attr_t * attr: Ici c'est pour changer le comportement du thread. Je ne l'ai jamais utilisé pour être franc. Nous mettrons donc l'attribut NULL
void * (* start_routine) (void *): Ici c'est le nom de la fonction à exécuter. Il est bien sûr complètement possible d'avoir 2 threads qui tournent avec la même fonction. D'ailleurs nous le verrons car c'est que je vais vous montrer en dessous.
void * arg: L'arguments passé à notre fonction lancée par le thread... C'est ici que tout va se jouer... Nous ne passerons qu'un seul argument, mais cet argument sera un structure. Ce qui nous mène tranquillement au prochain "chapitre"

0011: Déclarer une structure, et la remplir

Nous voici dans le "coeur" du tuto. Je rappel que je n'expliquerai pas ce qu'est une structure. Je pars du principe que vous connaissez et, si ce n'est pas le cas vous pourrez trouver des informations Veuillez vous enregistrer pour visualiser l'ensemble du forum en cliquant ici.

Je vais suivre le même exemple que dans le tuto précédent. Le code sera donc "presque" le même afin de pouvoir vous montrer les différences.

Bref rappel du code:
Celui-ci a pour but de lancer trois threads, puis d'afficher un numéro de thread (Thread[1-2-3]) et un compteur (i).

Donc il vous faut créer une structure comme celle-ci par exemple:

Code C :

struct ct
{
    int count;
    int nb;
};
 


Une fois la structure "construite", il nous faut une variable struct dans notre code. Pour ceux qui ne comprenne pas pourquoi, ça marche comme pour les types int,char,ect. Si vous avez besoin d'un i pour une boucle for(), vous le déclarez au dessus ou dedans (depuis la norme c99) de la manière suivante:

Code C :

[...]
int i;
for (i =0; CONDITION; i++){
    /* CODE */
}
// norme c99
for(int i =0; CONDITION; i++){
    /* CODE */
}
[...]
 


Donc nous allons tout bêtement déclarer notre structure de la manière suivante:

Code C :

struct struc_name name;
//ce qui donne dans notre cas:
struct ct ct_name
 


Ensuite il nous faut remplir cette structure. Dans celle-ci , nous pouvons voir qu'il y a deux éléments.
count => qui sera le i du for()
et
nb => qui lui sera le numéro du thread.

En partant de ce principe, nous avons besoin d'initialiser qu'une seule fois le count. En effet si on réfléchit un peu, notre count (i) partira de 0 pour les trois threads. Donc:

Code C :

ct_name.count = turn;
 

turn n'est que le nom de ma variable. ON le verra dans le code un peu plus tard.

Ensuite il nous faut initaliser le numéro du thread. MAis là une petite "subtilité" est de mise. En effet nous avons 3 threads, donc il nous faut 3 variables nb[1-2-3] et donc réinitialiser ct_name.nb 3 fois.

Code C :

ct_name.nb = nb1;
pthread_create(...)
ct_name.nb = nb2;
pthread_create(...)
ct_name.nb = nb3;
pthread_create(...)
 

Pour nb[1-2-3] idem que turn. Si nous ne le faisons pas, on se retrouvera avec trois threads qui porterons le même numéro. (Aucune incidence sur l'exécution du code en lui même, mais dans l'affichage si!)

0100: Création des threads plus envoi de la structure en arguments

Bon passons à la création de nos threads. En fait pas plus de difficultés. En effet nous allons passer les mêmes paramètres, sauf qu'au lieu de mettre l'adresse d'une variables en 4ème argument de pthread_create(), nous allons mettre l'adresse de notre structure fraichement créée.

Code :
pthread_create(&thread1, NULL, (void *)affichage, &ct_name);
pthread_create(&thread2, NULL, (void *)affichage, &ct_name);
pthread_create(&thread3, NULL, (void *)affichage, &ct_name);

Euh c'est tout ? bah oui!!! Pas très compliqué hein... Wink

On oublie pas les pthread_join() hein!! Wink

0101: Récupération des arguments dans la fonction

Bon nous avons nos threads, et maintenant on se retrouve dans la fonction qui va gérer l'affichage. Donc le but maintenant c'est de pouvoir récupérer nos arguments.
Rien de plus simple.
Le prototype de la fonction est:

Code C :

void affichage(int *);
 


Donc nous recréons une structure de la manière suivante:

Code :
struct ct *args = (void *)arguments;

Comme nous pouvons le voir, nous créons une structure à qui on affecte arguments et si on réfléchit un peu, arguments est déja égale à notre structure passée au thread. Donc en fait sans le savoir on viens de faire couler gentillement nos valeur turn et nb. Il nous suffit donc de les récupérer tout simplement de la manière suivante:

Code C :

int i = args->count;
int name = args->nb;
 


Et voilà nous avons tout ce qu'il nous faut pour traiter correctement notre affichage avec une jolie boucle for().

Code C :

for(; i<5; i++){
    printf("Thread%d: %d\n", name, i);
    sleep(3);
}
 

Vous remarquerez que je n'ai rien initialisé dans la première partie du for(). Normal car si on remonte le chemin à l'envers on obtient ceci:

Code C :

i = args->count = turn = 0
 

Wink

0110: Code/Résultat.

Aller pour que vous compreniez un peu mieux, voici le code:

Code C :

#include <pthread.h>
#include <stdio.h>  // printf()
#include <string.h> // strlen()
#include <unistd.h> // usleep()


struct ct
{
    int count;
    int nb;
};

/* Les sleep() sont seulement ici pour affiner l'affichage*/
void affichage(int *arguments){
    struct ct *args = (void *)arguments;
    int i = args->count;
    int name = args->nb;

    for(; i<5; i++){
        printf("Thread%d: %d\n", name, i);
        sleep(3);
    }
}


int main(int argc, char* argv[]){
    /* Ici on déclare nos threads:*/
    pthread_t thread1;
    pthread_t thread2;
    pthread_t thread3;

    /* Nos threads afficherons un int et leur numéro de thread*/
    int nb1 = 1;
    int nb2 = 2;
    int nb3 = 3;
    int turn = 0;
   
    /* Déclaration de la structure qui recevra nos arguments*/
    struct ct ct_name;
    /* On initialise une seul fois le compteur dans la structure. En effet celui-ci ne change pas contrairement au numéro de thread.*/
    ct_name.count = turn;

    /* Ici nous allons créer nos thread a l'aide de pthread_create() + on indique le numéro du thread dans la structure nb*/
    ct_name.nb = nb1;
    pthread_create(&thread1, NULL, (void *)affichage, &ct_name);
    sleep(1);
    ct_name.nb = nb2;
    pthread_create(&thread2, NULL, (void *)affichage, &ct_name);
    sleep(1);
    ct_name.nb = nb3;  
    pthread_create(&thread3, NULL, (void *)affichage, &ct_name);

    /* On attend que nos threads soient terminés avant la fin du programme*/
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);

    return 0;
}
 


Et Veuillez vous enregistrer pour visualiser l'ensemble du forum en cliquant ici. en couleur.

Le résultat reste le même à l'identique que dans le tuto précédent:

Code C :

shut@M1nT ~/scripts/C $ ./thread
Thread1: 0
Thread2: 0
Thread3: 0
Thread1: 1
Thread2: 1
Thread3: 1
Thread1: 2
Thread2: 2
Thread3: 2
Thread1: 3
Thread2: 3
Thread3: 3
Thread1: 4
Thread2: 4
Thread3: 4
shut@M1nT ~/scripts/C $
 


0111: Conclusion


Lorsque l'on commence à utiliser les threads, nous sommes vite confronté à cette situation de plusieurs arguments à faire passer. En effet travailler les threads avec un seul argument est vite USELESS si je puis dire. Smile

En éspérant vous avoir éclairé au mieux. Wink

Junky.

New Project News White Hat Hacker V2.3
Accueil | Challenges | Tutoriels | Téléchargements | Forum