[C] Lancement de plusieurs processus

Fermé
Bob l'éponge - 28 mai 2006 à 16:56
 Bob l'éponge - 31 mai 2006 à 18:35
Bonjour,

je suis débutant en programmation systeme, je sollicite votre aide pour m'aider à écrire le main de mon programme.
Pour l'écriture du programme, il faut uniquement que j'utilise des fork, pipe... car je n'ai pas vu les threads...

J'explique ce qu'il faut faire :
-avoir plusieurs traceroute s'effectuant simultanément, afin de rassembler des informations le plus vite possible
-pouvoir choisir à la volée combien de traceroute on souhaite exécuter en parallèle)
-ajouter de nouvelles « cibles » pour traceroute pendant que l'ensemble fonctionne.

Les résultats des traceroute (avec l'option -n) lancés doivent être écrits dans un fichier pour pouvoir analyser les lignes et ainsi créer un graphe.

Le parsing et la création du graphe ont été faits, c'est le lancement des traceroutes et l'écriture dans le fichier qui pose problème.

Voici ce que j'ai écrit. Il n'est pas complet et aimerait que vous m'aidez pour faire en sorte qu'il le soit.

Merci par avance

// structure pour gérer une info fils => père
typedef struct {
  info1;
  info2;
  info3;
  info4;
  //...les infos qu'il faut
} t_info;

// structure pour gérer un fils et son pipe
typedef struct {
  int cote[2];               // Cotés du pipe
  int pid;                  // PID du fils
} t_fils;

int main(void)
{
  t_fils tabFils[n];           // Tableau des fils
  int i;                           // Boucle
  int nbFils;                   // Nb fils vivants
  t_info info;                  // Info transmise
  
  // Création des processus
  for (i=0; i < n; i++)
    {
      // Ouverture du pipe pour le fils vers son père
      pipe(tabFils[i].cote);
      
      // Création du processus fils
      if ((tabFils[i].pid=fork()) == 0)
    {
      // Ici on est dans le fils "i"
      
      // On commence par fermer le coté de lecture inutile
      close(tabFils[i].cote[0]);
      
      // Traceroute vers ip X
      //...
      
      // Récupération de toutes les IP situées entre moi et "x" => tableau d'IP
      //..
      
      //  Transmission de ce tableau vers le père par le pipe
      for (//...)
      {
        // Remplissage infos (une des info pourrait être le n° du fils)
        info.info1=i;
        info.info2=//...
          //... (on remplit toutes les infos)
          
          // On envoie l'info au père
          write(tabFils[i].cote[1], &info, sizeof(info);
            
         // on envoie une info particulière signifiant "fini"
         write(tabFils[i].cote[1], "EOT", 4);
            
        // Toutes les Ip sont transmises - Fin du fils (mais fermeture pipe avant)
        close(tabFils[i].cote[1]);
        exit(0);
      }
        
      // Ici on est dans le père - On n'a rien à faire sauf à fermer le coté d'écriture inutile
    close(tabFils[i].cote[1]);
    }
 
        // Ici, tous les fils sont lancés - On scrute maintenant les pipes tant qu'il y a des fils
        nbFils=n;
      while (nbFils > 0)
      {
        // On lit tous les pipes des fils
        for (i=0; i < n; i++)
          {
        // Si le fils "i" n'existe plus on le saute
        if (tabFils[i].pid == 0)
          continue;
        
        // Lecture du pipe venant du fils "i"
        if (read(tabFils[i].cote[0], &info,  sizeof(info)) > 0)
          {
            // Si on a reçu l'info particulière "EOT"
            if (//... == "EOT")
            {
              // On ferme le pipe de ce fils
              close(tabFils[i].cote[0]);
              
              // Le fils a terminé => pid mis à 0 (permettra de ne plus le traiter)
              tabFils[i].pid=0;
              
              // Un fils en moins
              nbFils--;
              
              // Inutile d'en faire plus pour ce crevard
              continue;
            }
            
            // Ici, on a reçu les infos sur les IP pour le fils "i"
            //... => on les analyse et on construit le graphe
         }
            
        // ici, soit on n'a rien reçu, soit on a fini de traiter les infos => on reboucle sur le fils suivant
            sleep(1);
   }
}
// Ici, il n'y a plus de fils

}

11 réponses

Bob l'éponge
28 mai 2006 à 23:37
Salut,

est-ce que quelqu'un pourrais m'aider svp car je n'y arrive pas .

Merci
0
Bob l'éponge
29 mai 2006 à 13:32
Salut,
voici l'énonce du projet :
C'est la partie lancement des traceroute qui me posent problème.

J'aurais besoin d'aide car je bloque et mon projet est à rendre bientôt .

Merci



Le réseau Internet peut être grossièrement assimilé à un graphe, dont les noeuds sont les hôtes (machines, routeurs...) et les arêtes les liens entre ces hôtes. Depuis un noeud A donné, il est très difficile d'avoir une vue d'ensemble du réseau ; cependant, on peut effectuer un « traceroute » vers un autre noeud B, et dans la plupart des cas, obtenir une liste de noeuds formant un chemin entre A et B.


Sur Internet, une machine (ou un routeur, c'est pareil!) peut avoir 1 ou plusieurs adresses IP, et chaque adresse IP peut avoir 0, 1 ou plusieurs noms DNS rattachés. Inversement, un nom DNS peut être rattaché à 0, 1 ou plusieurs adresses IP. Comme les relations entre les adresses IP et les noms DNS sont complexes, on ignorera complètement les noms DNS. D'autre part, même si une machine peut avoir plusieurs adresses IP, on n'essaiera pas de « deviner » si plusieurs adresses appartiennent à la même machine ou pas. On raisonnera donc, finalement, en adresses IP plutôt qu'en machines ou routeurs ou noms DNS.

L'option -n de la commande traceroute permet de désactiver la résolution DNS (la conversion des adresses IP en noms)

~traceroute -n 192.48.96.9
traceroute to 192.48.96.9 (192.48.96.9), 30 hops max, 40 byte packets
 1  192.168.0.1  9.754 ms  9.461 ms  8.046 ms
 2  195.6.244.14  60.885 ms  48.924 ms  90.517 ms
 3  194.206.126.244  50.503 ms  48.97 ms  120.122 ms
 4  194.206.126.2  55.655 ms  52.213 ms  58.908 ms
 5  208.213.229.130  588.303 ms  589.843 ms  589.611 ms
 6  208.213.229.129  599.564 ms  599.763 ms  600.749 ms
 7  208.213.229.226  629.167 ms  599.284 ms  599.383 ms
 8  195.10.40.34  599.152 ms  599.289 ms  631.011 ms
 9  157.130.34.217  642.326 ms  715.072 ms  653.724 ms
10  146.188.160.62  595.143 ms  590.433 ms  659.247 ms
11  146.188.160.181  649.863 ms  700.901 ms  617.067 ms
12  137.39.253.86  600.835 ms  599.379 ms  590.867 ms
13  192.48.96.9  607.071 ms  589.221 ms  603.156 ms

Attention, le graphe d'Internet n'est pas forcément un graphe « idéal », et les chemins que vous verrez apparaître en faisant des « traceroute » ne seront pas forcément les meilleurs ou les plus courts. Ne vous étonnez pas si par exemple, sur un traceroute, vous voyez des chemins non-optimaux !

D'autre part, ce n'est pas non plus un graphe figé ni déterministe, donc d'un jour à l'autre (ou même d'une minute à l'autre) un même traceroute pourra donner des résultats différents.

But du projet

Il s'agit d'écrire un programme (ou un ensemble de programmes) permettant d'effectuer des traceroute automatiquement, en tâche de fond ; et pendant que se font ces traceroute, de rassembler des informations sur le graphe d'Internet. En particulier, pour chaque noeud du graphe (on assimilera un noeud à son adresse IP), on souhaite pouvoir connaître ses voisins, ainsi que sa distance minimale à l' « origine » (la distance n'est pas forcément constante, par exemple entre le noeud A et le noeud B, le noeud X peut apparaître en 5è position ; et le même noeud X peut apparaître en 8è position entre le noeud A et le noeud C -- c'est surprenant, mais c'est possible!).

Il est indispensable de pouvoir :

* avoir plusieurs traceroute s'effectuant simultanément, afin de rassembler des informations le plus vite possible ;
* pouvoir choisir à la volée combien de traceroute on souhaite exécuter en parallèle) ;
* ajouter de nouvelles « cibles » pour traceroute pendant que l'ensemble fonctionne ;

* ajouter des cibles « aléatoires » (en tirant des adresses IP au hasard) ;
* visualiser des statistiques indiquant le nombre d'adresses IP « explorées » (nombre total, et classement par distance par rapport à l'origine) ;
* indiquer les « voisins » d'un noeud donné par son adresse IP ;
* exporter (et importer) l'état du graphe, sous forme de deux fichiers CSV : un contenant la liste des sommets (adresses IP) avec leur distance minimale à la source, et un autre contenant une liste de couples d'adresses IP ;


Informations techniques

Une adresse IP = 4 octets. Généralement on la représente sous la forme 134.157.0.129 (sous forme de 4 nombres entiers, en décimal, séparés par des points).
Les plages d'adresses suivantes sont « privées », c'est-à-dire internes :

* 10.0.0.0 à 10.255.255.255
* 172.16.0.0 à 172.31.255.255
* 192.168.0.0 à 192.168.255.255

La plage 224.0.0.0 à 239.255.255.255 est réservée au multicast.
Les adresses de 240.0.0.0 à 255.255.255.255 sont réservées.
Toutes ces plages (adresses privées, multicast, réservées) ne doivent pas être traitées

Le format CSV à utiliser, pour la liste des noeuds : adresse IP, distance
1.2.3.4,17
134.157.0.129,8
193.55.63.92,2
Le format CSV à utiliser, pour la liste des arêtes : adresse IP1, adresse IP2
1.2.3.4,1.2.3.5
134.157.0.129,134.157.254.1
193.55.63.1,193.55.63.29
On utilisera \n comme séparateur de lignes.
0
Bob l'éponge
29 mai 2006 à 19:47
Salut,

est-ce que quelqu'un pourrait m'aider svp

Merci
0
Bob l'éponge
29 mai 2006 à 20:54
Salut,

j'ai un peu modifié le code précédent.

Si quelqu'un pouvait m'aider, svp pour avoir du code compilable?

Merci

void traite_fils(t_info* info, t_fils* tuyau) {
    for (i=0; i < n; i++) {
         // Traceroute vers ip X
      //...
      
      // Récupération de toutes les IP situées entre moi et "x" => tableau d'IP
      //..
      
      //  Transmission de ce tableau vers le père par le pipe
      for (//...)
      {
        // Remplissage infos (une des info pourrait être le n° du fils)
        info->info1=i;
        info->info2=//...
          //... (on remplit toutes les infos)
          
          // On envoie l'info au père
          write(tuyau->cote[1], info, sizeof(*info);
            
         // on envoie une info particulière signifiant "fini"
         write(tuyau->cote[1], "EOT", 4);
            
        // Toutes les Ip sont transmises - Fin du fils (mais fermeture pipe avant)
        close(tuyau->cote[1]);
        exit(0);
    }
}

int main(void)
{
  t_fils tabFils[n];           // Tableau des fils
  int i;                           // Boucle
  int nbFils;                   // Nb fils vivants
  t_info info;                  // Info transmise
  
  // Création des processus
  for (i=0; i < n; i++)
    {
      // Ouverture du pipe pour le fils vers son père
      if (pipe(tabFils[i].cote) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
      }
      
      // Création du processus fils
      tabFils[i].pid = fork();
      switch (tabFils[i].pid)
    {
        case -1:
            perror("fork");
            exit(EXIT_FAILURE);
        case 0:  // Ici on est dans le fils "i"  
            // On commence par fermer le coté de lecture inutile
            close(tabFils[i].cote[0]);
            traite_fils(&info,&tabFils[i]);
            break;
        default:
            // Ici on est dans le père - On n'a rien à faire sauf à fermer le coté d'écriture inutile    
            close(tabFils[i].cote[1]);
            break;
    }
 

  // on est sur d'etre dans le pere...
 
 
        // Ici, tous les fils sont lancés - On scrute maintenant les pipes tant qu'il y a des fils
        nbFils=n;
      while (nbFils > 0)
      {
        // On lit tous les pipes des fils
        for (i=0; i < n; i++)
          {
        // Si le fils "i" n'existe plus on le saute
        if (tabFils[i].pid == 0)
          continue;
        
        // Lecture du pipe venant du fils "i"
        if (read(tabFils[i].cote[0], &info,  sizeof(info)) > 0)
          {
            // Si on a reçu l'info particulière "EOT"
            if (//... == "EOT")
            {
              // On ferme le pipe de ce fils
              close(tabFils[i].cote[0]);
              
              // Le fils a terminé => pid mis à 0 (permettra de ne plus le traiter)
              tabFils[i].pid=0;
              
              // Un fils en moins
              nbFils--;
              
              // Inutile d'en faire plus pour ce crevard
              continue;
            }
            
            // Ici, on a reçu les infos sur les IP pour le fils "i"
            //... => on les analyse et on construit le graphe
         }
            
        // ici, soit on n'a rien reçu, soit on a fini de traiter les infos => on reboucle sur le fils suivant
            sleep(1);
   }
}
// Ici, il n'y a plus de fils

}
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Bob l'éponge
30 mai 2006 à 10:22
Salut,

Est-ce que quelqu'un pourrait m'indiquer à quel momment dans le code lancé les traceroute ainsi que le fait de mettre le résultat dans un fichier car je doit le parser pour créer le graphe.

la fonction de parsing à ce prototype char **Parsing(FILE *fichier) et la création du graphe CreerGraphe(char **tab).

Svp, pouvez-vous m'aider à avoir un main complet

Merci par avance
0
Bob l'éponge
30 mai 2006 à 15:07
Bonjour,

pouvez-vous m'aider svp, mon projet est à rendre demain?

Merci
0
ollie314 Messages postés 145 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 26 octobre 2007 80
30 mai 2006 à 15:24
Bonjour,

Je vais essayé. Je regarde ton code et l'ennoncé de ton projet

Jete répond après.

Amicalement
Ollie314
0
Bob l'éponge
30 mai 2006 à 20:05
Salut,

est-ce que tu as pu regarder pour mon problème?
J'ai vraiment besoin d'aide, c'est pour demain


J'ai pensé à quelques trucs que j'arrive pas à mettre en pratique.
Il me faudrait de l'aide pour écrire le programme complet, svp



Il faut pas que les fils fassent du "traceroute" dans un fichier. Chaque fils exploite lui-même la commande "traceroute" ligne par ligne avec un "popen()" et analyse chaque ligne pour en extraire les IP. Il crée ensuite un tableau d'IP qu'il transmet au père. Le père crée l'arbre.
Ensuite, pour l'ajout "en live" d'un nouveau "traceroute", j'ai pas trop d'idée précise.

Voilà à peu près l'idée de base
On lance le père avec la liste des IP à tester en paramètre. Le père crée un tableau d'IP (tableau dynamique)
Ensuite, il part en boucle infinie de cette façon:
BOUCLE INFINIE
FAIRE
POUR CHAQUE IP de la liste d'IP
FAIRE
créer un fils puis récupérer ses infos et les intégrer dans l'arbre
FIN FAIRE

trouver ici un moyen pour pouvoir rajouter des IP dans la liste d'IP sur un évènement extèrieur, et là, j'en sais rien.

FIN FAIRE
0
ollie314 Messages postés 145 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 26 octobre 2007 80
30 mai 2006 à 21:43
bonjour,

J'ai regardé ton code. Il est finement pensé. Il faut effectivement, dans ton cas attendre la fin de l'exécution de la boucle infinie pour ajouter de traitements.

Je pense que ta liste d'ip devrait être réaliser via un fichier. La manipulation n'est pas aisé mais bon...

L'idée est d'ajouter les ip que tu veux traiter à ce fichier à la volé et dès que le père débute son traitement il enregistre l'ip et la supprime du fichier. Je trouve cela scabreux car si deux fils tente d'accèder en même temps au fichier il y aura conflit et il faut prévoir une opération qui suspend l'écriture jusqu'à ce que le fichier soit accessible. C'est plutôt long, mais ça devrait fonctionner.

Pour l'ensemble du programme, je ne suis pas certains qu'il ne faille pas faire une modification au niveau des structures. Pour ma part j'aurais intégré les traitements dans les structures et implémenté une recursivité (avec le danger de créer une boucle infinie ingérable, je n'ai pour l'instant pas d'idée sur le comment tester l'arrêt de la boucle infinie)

Ton projet est vraiment interressant, je vais m'y coller dès que j'aurais le temps.

Amicalement

Ollie314
0
Bob l'éponge
31 mai 2006 à 18:21
Salut,

svp, pouvez-vous m'aider?

Personne ne sait comment faire ?
0
Bob l'éponge
31 mai 2006 à 18:35
Salut,

svp, pouvez-vous m'aider?

Personne ne sait comment faire ?
0