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 :

fork() wait () kill ()


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Webmaster
    Inscrit en
    Mai 2011
    Messages
    258
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Webmaster
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2011
    Messages : 258
    Par défaut fork() wait () kill ()
    Bonjour,

    Je me met au C sous Linux.

    J'ai des bonnes bases pour le C sous MS-DOS, mais je dois avouer que je bloque quelques peu sur les problèmes ci-dessus.

    Ma question est :

    Où peut-on lire un listing avec des processus père et fils ( fork ) , qui attendent un signal ( wait et kill ) et qui exécutent un handler.

    Ce que j'ai lu est très abstrait et il me manque des exemples pour approfondir ma compréhension.

    Mais peut-être, il y a t il un cours sur le site, dans ce cas je ne l'ai pas vu .

  2. #2
    Membre expérimenté

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 329
    Par défaut
    Salut !!

    J'ai fait à l'époque un petit programme servant à démontrer le fonctionnement de l'interception des signaux (kill) par un programme.
    Ca te donnera déjà une petite idée de la mise en place d'un "handler".

    Concernant le fork()... j'ai des applications qui l'utilisent mais je passe le plus souvent par les threads posix, voici le seul exemple que j'ai trouvé utilisant le fork().
    Fichiers attachés Fichiers attachés

  3. #3
    Membre éclairé
    Homme Profil pro
    Webmaster
    Inscrit en
    Mai 2011
    Messages
    258
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Webmaster
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2011
    Messages : 258
    Par défaut Merci pour les exemples
    Je vais potasser tout ça.

    Mais quelle est vraiment l'utilité de créer un processus fils ?

    Est-ce pour le cas d'une commande qui demande un long temps d'exécution au fils qui permet ainsi au
    processus père de continuer de travailler ?

    A part cela, je ne vois pas.

  4. #4
    Membre expérimenté

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 329
    Par défaut
    Dans le cas où tu veuilles faire un "service" (un daemon) sous Linux, en général nous procédons de la sorte.

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 835
    Billets dans le blog
    1
    Par défaut
    Salut
    Citation Envoyé par frederic13870 Voir le message
    J'ai des bonnes bases pour le C sous MS-DOS
    Dommage, Unix (et son petit frère Linux) ayant été écrits en C, le C est particulièrement adapté sur ces OS. C'est même pour cela que le C est enseigné dans les écoles d'ingénieur. Ceci dit, tu as commencé par le plus difficile (C sur un OS qui n'est pas adapté) donc venir au C sous Linux devrait te sembler... rafraichissant.

    Citation Envoyé par frederic13870 Voir le message
    Mais quelle est vraiment l'utilité de créer un processus fils ?

    Est-ce pour le cas d'une commande qui demande un long temps d'exécution au fils qui permet ainsi au
    processus père de continuer de travailler ?

    A part cela, je ne vois pas.
    Déjà le shell fait cela par défaut. Quand tu appelles une commande (ex ls -l), le shell commence par lancer un fils. Le fils bascule ensuite sur le "ls" via la fonction execl() tandis que le père se met en attente de la fin du fils.
    A quoi cela sert ? Ben il te suffit de rajouter un "&" à la fin de ta commande (ex ls -l &) et là le père n'attend plus, il revient immédiatement à l'écoute d'une autre commande. C'est parce que le shell est déjà programmé pour générer un fils à chaque commande que lui rajouter la possibilité de mettre cette commande en "arrière plan" est facile (suffit juste que le père n'attende pas la fin du fils c'est à dire ne pas exécuter le wait(). Alors que s'il avait fallu faire le contraire (c'est à dire ne générer la commande dans un fils qu'en cas de demande en arrière plan) cela aurait été bien plus lourd à coder.

    Il y a aussi les serveurs, c'est à dire des programmes qui attendent une requête (au hasard serveur web, serveur bdd, etc) venant d'un client quelconque. Quand la requête arrive ils génèrent un fils chargé de s'en occuper tandis qu'eux reviennent à l'écoute de la requête suivante (client suivant).

    Citation Envoyé par frederic13870 Voir le message
    Où peut-on lire un listing avec des processus père et fils ( fork ) , qui attendent un signal ( wait et kill ) et qui exécutent un handler.
    Il y a quelques années j'avais tapé un petit exemple montrant un programme qu'on ne peut arrêter
    Code c : 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
    #include <stdio.h>
    #include <unistd.h>
    #include <signal.h>
     
    void handler(int s) {
    	// signal(s, handler);		// A décommenter sur un OS plus vieux sur lequel le handler est désarmé à réception du signal => il faut alors le réarmer
    	printf("Je suis HIGHLANDER !!! Je suis INVULNERABLE au signal %d\n !!!", s);
    }
     
    int main() {
    	unsigned long i;
    	for (i=1; i <= SIGRTMAX; i++) signal(i, handler);
     
    	i=1;
    	while (1) {
    		printf("(i=%lu) - Je suis pid=%d - Essayez de me tuer...\n", i, getpid());
    		if ((i% 10) == 0) printf("... et ça commence à devenir long !!!\n");
    		i++;
    		sleep(1);
    	}
    }
    Bon manque le fork car tout se déroule dans le père mais ça reste compréhensible je pense. J'avais fait aussi un ping-pong entre deux processus mais je ne le retrouve pas. S'il t'intéresse je le réécrirai.
    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]

  6. #6
    Membre éclairé
    Homme Profil pro
    Webmaster
    Inscrit en
    Mai 2011
    Messages
    258
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Webmaster
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2011
    Messages : 258
    Par défaut merci, c'est plus clair
    Et voici un exemple, plus sophistiqué que j'ai glané sur le man du raspberry pi Buster :

    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
     
    /* The following shell session demonstrates the use of the program:
     
               $ ./a.out &
               Child PID is 32360
               [1] 32359
               $ kill -STOP 32360
               stopped by signal 19
               $ kill -CONT 32360
               continued
               $ kill -TERM 32360
               killed by signal 15
               [1]+  Done                    ./a.out
               $
    */
     
           #include <sys/wait.h>
           #include <stdlib.h>
           #include <unistd.h>
           #include <stdio.h>
     
           int main(int argc, char *argv[])
           {
               pid_t cpid, w;
               int wstatus;
     
               cpid = fork();
               if (cpid == -1) {
                   perror("fork");
                   exit(EXIT_FAILURE);
               }
     
               if (cpid == 0) {            /* Code executed by child */
                   printf("Child PID is %ld\n", (long) getpid());
                   if (argc == 1)
                       pause();                    /* Wait for signals */
                   exit(atoi(argv[1]));
     
               } else {                    /* Code executed by parent */
                   do {
                       w = waitpid(cpid, &wstatus, WUNTRACED | WCONTINUED);
                       if (w == -1) {
                           perror("waitpid");
                           exit(EXIT_FAILURE);
                       }
     
                       if (WIFEXITED(wstatus)) {
                           printf("exited, status=%d\n", WEXITSTATUS(wstatus));
                       } else if (WIFSIGNALED(wstatus)) {
                           printf("killed by signal %d\n", WTERMSIG(wstatus));
                       } else if (WIFSTOPPED(wstatus)) {
                           printf("stopped by signal %d\n", WSTOPSIG(wstatus));
                       } else if (WIFCONTINUED(wstatus)) {
                           printf("continued\n");
                       }
                   } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
                   exit(EXIT_SUCCESS);
               }
           }
    Compilé avec gcc sius DEBIAN, ce programme fonctionne parfaitement.

    Est-ce que quelqu'un se sent de m'expliquer le fonctionnement ?

    Surtout la condition du " do " que je ne comprends pas.

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par frederic13870 Voir le message
    Est-ce que quelqu'un se sent de m'expliquer le fonctionnement ?

    Surtout la condition du " do " que je ne comprends pas.
    Un père lance un fils, puis attend que le fils se termine, d'où ce "do" qui permet au père de boucler sur cette attente.
    Une fois le fils terminé, il récupère son état de sortie et affiche cet état.

    Et c'est là que ça devient intéressant car un processus (par exemple le fils comme ici) peut s'arrêter de deux façons
    • de lui-même via exit(n) (0 <= n <= 255)
    • par un signal "s" envoyé depuis l'extérieur via kill(s) (1 <= s <= 64). A quelques exceptions près comme 19 (SIGSTOP) qui suspend le processus et 18 (SIGCONT) qui le relance, et 9 (SIGKILL) qui s'adresse non pas au processus lui-même mais à l'ordonnanceur de tâche en lui demandant de virer le processus de la liste des processus à exécuter ce qui fait que ce signal là ne peut pas être "trappé" par ledit processus, les processus "meurent" quand ils reçoivent un signal

    Le père, quand il récupèrera cet êtat, doit pouvoir distinguer de quelle façon s'est arrêté le fils. Hé bien il récupère cet état dans un int (16 bits). Et si le fils a été arrêté par exit(n) la valeur "n" se trouve stockée dans les 8 premiers bits de l'int, et si c'est kill(s) la valeur "s" se trouve stockée dans les 8 derniers bits de l'int.
    Suffit donc de regarder ces 8 derniers bits et s'ils sont à 0 ("s" ne pouvant pas être égal à 0) c'est que c'était exit(n) et sinon c'était kill(s). Suffit ensuite d'extraire les bits adéquats pour récupérer "s" ou "n".
    Et comme cette procédure peut évoluer demain, elle a été encapsulée dans 4 macros
    • WIFEXITED() qui indique si c'était exit()
    • WIFSIGNALED() qui indique si c'était kill()
    • WEXITSTATUS() qui récupère le "n" de exit(n)
    • WTERMSIG() qui récupère le "s" de kill(s)

    Plus deux macros WIFSTOPPED() qui indique si un processus est stoppé (pas arrêté, juste mis en pause) et WIFCONTINUED() qui indique s'il est reparti.

    Donc la condition du "do", c'est "si pas de sortie par kill() ou exit()".
    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]

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

Discussions similaires

  1. Fork & wait(0)
    Par stoner dans le forum Débuter
    Réponses: 7
    Dernier message: 14/02/2013, 02h38
  2. [debutant] fork et wait
    Par nyakooza dans le forum Linux
    Réponses: 4
    Dernier message: 26/08/2008, 21h27
  3. fork() wait() waitpid() et companie
    Par guillaume_60 dans le forum POSIX
    Réponses: 3
    Dernier message: 23/05/2006, 12h03
  4. fork kill
    Par krusaf dans le forum Windows
    Réponses: 5
    Dernier message: 01/09/2005, 11h32
  5. fork wait
    Par lafracas dans le forum POSIX
    Réponses: 2
    Dernier message: 19/03/2005, 11h57

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