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 :

Aide sur les fork


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2013
    Messages : 95
    Par défaut Aide sur les fork
    Bonjour, je suis en étude d'informatique et je suis actuellement en session d'examen. J'ai mon examen de système d'exploitation bientôt et je voudrai être sur que ma synthèse ne comporte pas d'erreur. Et que j'ai bien compris toute les notions vu en cour.

    1. L'instruction fork(). Quel est le rôle de cette instruction? Faire une comparaison des deux

      processus résultants.

      Fork() à pour effet de cloner un processus. Tout est cloné à part les adresses mémoires qui sont propres à chacun. Il possède chacun un identifiant unique (PID)

      Le clone(fils) hérite des descripteurs des ressources.
    2. Après un fork, qui est le père, qui est le fils?

      int fork() ; renvoit un entier qui peut avoir 3 valeurs :

      - si <0 = erreur
      - si 0 = vous êtes le fils
      - si >0 = vous êtes le père
    3. Comment faire communiquer deux processus ayant un lien de parenté? Donnez un exemple d'implémentation de la méthode, pas de code mais un algorithme.

      Pour faire communiquer 2 processus avec un lien de parenté, on utilse :

      -Les tubes anonymes

      int tube[2] où tube[0] désigne la sortie du tube (où on lit)

      tube[1] désigne l’entrée du tube (où on écrit)

      On crée ensuite le tube avec pipe(tube).

      Si la fonction renvoit une valeur <0, il y a une erreur lors de la création.

      Pour écrire, on utilise l’instruction : write(tube[1], var, sizeof(var))

      Sans oublier de fermer préalablement la sortie du tube : close(tube[0])

      Pour lire, on utilise l’instruction : read(tube[0], var, sizeof(var))

      Et on fermera préalablement l’entrée du tube : close(tube[1])

      Exemple d’implémentation :

      -On initialise le tube (int tube[2])
      -On pipe. Si la valeur renvoyée est < 0 : erreur, on stoppe.

      Sinon,

      -On fork et on met la valeur renvoyée dans une variable pid de type pid_t. Si pid < 0 : Erreur, on stoppe.

      Sinon,

      -Si pid == 0, on est le fils. On ferme l’entrée du tube (tube[1]) et on lit la sortie du tube (tube[0]) avec l’instruction « read » décrite plus haut.
      -Si pid > 0, on est le père. On ferme la sortie du tube (tube[0]) et on écrit à l’entrée du tube (tube[1]) avec l’instruction « write » décrite plus haut.

      On attend la fin du fils avec l’instruction « wait(0) »

      -Fin du programme.
    4. Comment faire communiquer deux processus n’ayant pas de lien de parenté? Expliquez trois méthodes. Donnez un exemple d'implémentation de la méthode que vous voulez, pas de code mais un algorithme.

      -Fichier : Chaque processus peut lire et écrire dans un fichier qui leur est connu.
      -File de message :
      -Tube nommé : Permettent à des processus sans lien de parenté de communiquer en mode flot (stream).

      Exemple d’implémentation :

      Le 1er processus :

      ·Creation du tube
      ·Ouverture en ecriture
      ·Ouverture en lecture
      ·Fermeture en ecriture
      ·Fermeture en lecture
      ·Suppression du tube (unlink)
    5. Comment faire communiquer deux fils d'un même père, ensembles? Donnez un exemple d'implémentation de la méthode, pas de code mais un algorithme.

      Si les deux fils doivent communiquer dans les deux sens (écrire et lire) on doit initialiser deux tubes.

      Exemple d’implémentation :
    6. Comment le père peut-il récupérer le statut de fin d'un de ses fils? Donnez un exemple d'implémentation de la méthode.

      On attends la fin du fils avec un wait(&status) (ou de waitpid(-1,&status, 0|WNOHANG|WUNTRACED)). Après on peut récupérer le statut de fin grace à différentes macros.

      On vérifie d’abord que le fils c’est terminé correctement avec « (WIFEXITED(status)) ». Si la macro a retourné TRUE, on recupère le code de retour du fils avec « WEXITSTATUS(status) ».

      Exemple d’implémentation :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      int status ;
       
      wait(&status) ;
       
      if (WIFEXITED(status)){
       
          écrire (« Processus terminé, code de retour : » WEXITSTATUS(status))
       
      }
      Fin du programme
    7. Comment un père peut-il être certain de la fin de tous ses fils avant de se terminer?

      Donnez un exemple d'implémentation de la méthode.

      En faisant une boucle de wait() qui boucle autant de fois qu’il y a de fils. Si la fonction wait() retourne -1, il y a une erreur. Sinon le fils s’est bien terminé.

      A la fin de la boucle, on est alors certain que tous les fils se sont bien terminés.

      Exemple d’implémentation :

      Un père crée x fils et attend leur fin pour se terminer.
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      int status ;
       
      for(i=0 ; i<x ; i++){
       
          if (wait(&status) == -1){
          perror(« wait : ») ;
       
          exit(1) ;
          }
          else{
              printf(« Le fils s’est bien terminé ») ;
          }
       
      }
      Fin du programme

    8. Expliquer comment utiliser les tubes nommés pour faire communiquer deux processus

      n'ayant pas de parenté directe.

      Grâce à la fonction mkfifo on peut crée deux tube nommé reliant deux processus n’ayant pas le même parent et spécidié les droits d’accès. La fonction renvoie 0 en cas de succès et -1 si echec. Il faux ouvrir les tubes en lecture et écriture sinon la communication sera bloquante.

      Pour ouvrir en mode lecture non bloquant :

      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
      int fd_write, fd_read;
       
      if ( (mkfifo("tube1",S_IRUSR|S_IWUSR) == -1) ||(mkfifo("tube2",S_IRUSR|S_IWUSR) == -1)){
       
          perror ("mkfifo"); exit (1);
       
      }
       
      if (( fd_write = open ("tube1", O_WRONLY)) == -1) {
       
          perror ("open"); exit (2);
       
      }
       
      if (( fd_read = open ("tube2", O_RDONLY)) == -1) {
       
          perror ("open"); exit (3);
    9. Comment récupérer le résultat de l'exécution d'un programme système? Expliquer l'implémentation de la fonction utilisée.

      je ne sais pas

  2. #2
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    Ta synthèse a l'air très correcte !

    Pour la dernière question, je me demande si ça n'était pas "appel système" plutôt que "programme système".
    Dans le cas d'un syscall/appel système, tu dois vérifier la valeur retour, et si elle correspond à un statut d'erreur, il faut lire la variable "errno" et/ou utiliser la fonction "perror".
    Sinon.... tout s'est bien passé... et tu peux utiliser "strace" pour tracer les sycalls...
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  3. #3
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2013
    Messages : 95
    Par défaut
    merci beaucoup. maintenant je peux étudier sans peur d'apprendre des imbécilité

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 477
    Par défaut
    Bonjour,

    Ta synthèse me semble également valable dans l'ensemble, mais avec quelques petites remarques toutefois :

    Citation Envoyé par Linquisiteur Voir le message
    L'instruction fork(). Quel est le rôle de cette instruction? Faire une comparaison des deux processus résultants.

    Fork() à pour effet de cloner un processus. Tout est cloné à part les adresses mémoires qui sont propres à chacun. Il possède chacun un identifiant unique (PID)

    Le clone(fils) hérite des descripteurs des ressources.
    Tout cela est vrai dans le principe mais sur les machines actuelles, les MMU permettent de mapper tous les processus dans le même plan mémoire apparent.

    Après un fork, qui est le père, qui est le fils?

    int fork() ; renvoit un entier qui peut avoir 3 valeurs :

    - si <0 = erreur
    - si 0 = vous êtes le fils
    - si >0 = vous êtes le père
    Vrai également mais pense à préciser que si « fork() >0 », la valeur retournée est le PID du fils, car c'est non seulement une info pertinente mais c'est le seul moyen de l'obtenir puisqu'un fils n'a qu'un seul père mais qu'un père peut avoir plusieurs fils.

    Pour écrire, on utilise l’instruction : write(tube[1], var, sizeof(var))
    Juste pour le principe, on ne met pas a priori de parenthèse à sizeof. Cela dit, ce n'est pas la peine de t'embêter avec cela maintenant, surtout qu'il est possible que ton prof' ne le sache pas non plus.

    [*]Comment un père peut-il être certain de la fin de tous ses fils avant de se terminer?

    Donnez un exemple d'implémentation de la méthode.

    En faisant une boucle de wait() qui boucle autant de fois qu’il y a de fils. Si la fonction wait() retourne -1, il y a une erreur. Sinon le fils s’est bien terminé.

    A la fin de la boucle, on est alors certain que tous les fils se sont bien terminés.
    Ça, par contre, ce n'est pas suffisant : comme tout appel système, il peut y avoir une multitude de raisons qui l'amènent à échouer et, surtout, la réception d'un signal « débloque » l'appel, provoquant un tour de boucle que tu interpréteras à tort comme la mort d'un fils si tu n'y prends pas garde.

    La man page nous enseigne en revanche que wait() échoue avec l'erreur ECHLD s'il n'y pas (ou plus) de fils à attendre. C'est donc le meilleur indicateur qui soit.

    [*]Expliquer comment utiliser les tubes nommés pour faire communiquer deux processus n'ayant pas de parenté directe.

    Grâce à la fonction mkfifo on peut crée deux tube nommé reliant deux processus n’ayant pas le même parent et spécidié les droits d’accès. La fonction renvoie 0 en cas de succès et -1 si echec. Il faux ouvrir les tubes en lecture et écriture sinon la communication sera bloquante.

    Pour ouvrir en mode lecture non bloquant :

    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
    int fd_write, fd_read;
     
    if ( (mkfifo("tube1",S_IRUSR|S_IWUSR) == -1) ||(mkfifo("tube2",S_IRUSR|S_IWUSR) == -1)){
     
        perror ("mkfifo"); exit (1);
     
    }
     
    if (( fd_write = open ("tube1", O_WRONLY)) == -1) {
     
        perror ("open"); exit (2);
     
    }
     
    if (( fd_read = open ("tube2", O_RDONLY)) == -1) {
     
        perror ("open"); exit (3);
    Oui mais n'oublie pas pas que :
    1. Les processus homologues doivent ouvrir un tube respectivement en lecture et en écriture. Donc, l'un d'eux doit faire O_RDONLY sur « tube1 » et l'autre sur « tube2 », et inversement avec O_WRONLY ;
    2. Qu'idéalement, il faudrait retirer les tubes nommés après usage (qui vont sur le système de fichier).


    [*]Comment récupérer le résultat de l'exécution d'un programme système? Expliquer l'implémentation de la fonction utilisée.

    je ne sais pas
    Il faudrait savoir ce qu'est un « programme système » en effet. Cela dit, je vois deux possibilités :

    • Utiliser « system() » ;
    • Lancer un processus avec « popen() ».

  5. #5
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2013
    Messages : 95
    Par défaut
    bonjour, merci de tous ces détail j'améliorerais ma synthèse demain matin (après un des examens ^^') Comme je n'aurais pas beaucoup de temps pour poser d'autre question je pose directement (et après go bosser sur l'exam de demain xD)

    Ça, par contre, ce n'est pas suffisant : comme tout appel système, il peut y avoir une multitude de raisons qui l'amènent à échouer et, surtout, la réception d'un signal « débloque » l'appel, provoquant un tour de boucle que tu interpréteras à tort comme la mort d'un fils si tu n'y prends pas garde.

    La man page nous enseigne en revanche que wait() échoue avec l'erreur ECHLD s'il n'y pas (ou plus) de fils à attendre. C'est donc le meilleur indicateur qui soit.
    J'ai du mal a comprendre ce point. En gros le programme peut avoir un bug d'origine diverse qui peut renvoyer une erreur qui sera interpréter comme la mort d'un fils ?

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 832
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Linquisiteur Voir le message
    J'ai du mal a comprendre ce point. En gros le programme peut avoir un bug d'origine diverse qui peut renvoyer une erreur qui sera interpréter comme la mort d'un fils ?
    Salut
    C'est ça. Il peut y avoir plusieurs causes qui amènent wait() à renvoyer -1. Et donc regarder si wait() vaut -1 n'est pas suffisant pour affirmer que c'est dû au fait qu'il n'y a plus de fils.
    La bonne méthode est de vérifier à la fois wait() et à la fois la valeur de errno.
    Si wait() a renvoyé -1 et que errno vaut ECHLD alors là tu es certain que c'est parce qu''il n'y a plus de fils en cours.

    Ce prédicat est d'ailleurs valable pour d'autres opérations système. Généralement il est souvent important d'associer le retour -1 d'une fonction système avec la valeur de errno...

    PS: je ne sais pas si t'as le droit d'en parler mais t'as aussi waitpid() qui permet de cibler un fils précis...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Février 2013
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2013
    Messages : 95
    Par défaut
    Ce que le prof attend de nous est que l'on ai comprit la matière vus en cour. Donc je dois être précis mais je ne suis pas obliger de l'être trop.
    Enfin merci. Demain je vais relire tout vos commentaire et rajouter quelques info à ma synthèse. Deux trois notion non vus en cour mais aux dernier examen où j'ai ajouter des notions non vus mais plus précise sa ma rafler un 18/20 ^^'
    J'en ai bien besoin car il a 4-5 des examens de fin d'années qui ont des taux d'echec de 80% alors il faut trouver les points ailleurs ..

    Sa ne dérange personne si je pose d'autre question en c plus tard? Car pour mon examen de c on risque des questions assez vicieuse.. (très!)

Discussions similaires

  1. besoin d'aide sur les ORB
    Par floorfille dans le forum CORBA
    Réponses: 4
    Dernier message: 24/08/2004, 15h43
  2. Aide sur les groupes (ADO)
    Par portu dans le forum QuickReport
    Réponses: 3
    Dernier message: 18/08/2004, 16h13
  3. Filemaker ... besoin d'aide sur les Plugin
    Par joange dans le forum Autres SGBD
    Réponses: 3
    Dernier message: 22/04/2004, 10h16
  4. Petite aide sur les triggers ?
    Par krimson dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 16/04/2004, 16h28
  5. [CR] besoin d'aide sur les formules
    Par GuillaumeDSA dans le forum Formules
    Réponses: 4
    Dernier message: 10/07/2003, 12h19

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