pb de processus zombies [Serveur en C ] - C - Programmation
Marsh Posté le 11-10-2004 à 20:25:13
pourquoi pas les thread ?
tu veux virer tes zombies ? il te faut faire des wait ...
Marsh Posté le 11-10-2004 à 20:42:54
Tu peux également faire le tout dans une seul thread, dans un seul processus, en utilisant select pour être en attente de tes clients.
C'est ce principe qu'utilisent beaucoup d'outils (mais en utilisant d'autres APIs que select, qui est un peu trop limité, et qui est généralement déconseillé).
Marsh Posté le 11-10-2004 à 20:55:15
ouais, mais avec le select, ça se complique si t'as un peu de travail à faire avec chaque client.
En fait le mieux, c'est un pool de thread
Tiens quelqu'un connaît une bibliothèque pour faire ça ?
Sinon les threads sur système unix, ça passe par :
- les POSIX threads
- les Portable Threads (libpth) qui est une très bonne alternative
Marsh Posté le 11-10-2004 à 21:22:05
bad11 a écrit : Coucou ! |
Quand un fils meurt, il reste à l'état de "zombie" tant que son père n'a pas consulté son état. Un des moyens de connaître l'état d'un fils est d'utiliser la primitive "wait".
Comment on s'en sert
1) tu déclares dans le père une variable style "int etat"
2) tu appelles dans le père "wait(&etat)"
Qu'est-ce qu'il va se passer
Si le fils est encore en vie, ton appel à "wait()" dans le père va bloquer ce dernier jusqu'à ce que le fils se termine.
Dès que le fils meurt (ou s'il est mort avant l'appel à "wait()" ), cet appel est débloqué et la fonction renvoie le pid du fils mort (utile dans le cas de plusieurs fils).
Ensuite, ta variable "etat" contiendra la cause de la mort du fils
- si le fils s'est terminé par "exit(n)", la valeur "n" sera dans le premier octet de la variable "etat" et l'autre octet sera à 0
- si le fils s'est terminé par "kill(n)", la valeur "n" sera placée dans les sept derniers bits de "etat". De plus, le 8° bit sera à "1" si le kill a provoqué la création d'un fichier core.
Tu peux utiliser les macros "WIFEXITED()", "WIFSIGNALED()", "WEXITSTATUS()" et "WTERMSIG()" définies dans "sys/wait.h" en y passant ta variable "etat". Ces macros vont tester et/ou extaire de "etat" l'octet qui va bien pour vérifier si la mort a été due à "exit" ou "kill" et récupérer la valeur de "exit" ou de "kill".
Le prpblème de "wait" est que c'est bloquant. De plus, tu ne peux pas cibler quel fils tu attends. Cependant, il y a des dérivés de "wait()" comme "waitpid().
Cette primitive est intéressante pour toi car elle permet de cibler quel processus on attend, et elle possède un paramètre "option" dans lequel tu peux y mettre la macro "WNOHANG" (mode non-bloquant) => ton serveur reste parallèle => la fonction renvoie "0" si le fils n'est pas encore fini
Si c'est trop compliqué ou trop lourd, tu peux alors utiliser des thread mais ça, je ne sais pas le faire...
Marsh Posté le 11-10-2004 à 22:49:25
je vous remercie je testerai cela demain a l'iut.
J'avais testé la fonction waitpid() avec WNOHANG mais j'avais pas réussi a la faire tourner et je n'avais pas insisté car je ne pensais pas etre sur la bonne voie.
Je retenterai demain.
Merci a tous pour vos conseils : la suite demain soir ! / Thanks Sve@r pour cette bonne explication en français et non remplie de mots barbares linuxiens ^^.
Marsh Posté le 12-10-2004 à 05:36:05
L'autre moyen de ne pas avoir de zombies, c'est d'écouter SIGCHLD. Tu peux même te contenter de faire un signal(SIGCHLD, SIG_IGN).
Marsh Posté le 12-10-2004 à 07:56:21
matafan a écrit : L'autre moyen de ne pas avoir de zombies, c'est d'écouter SIGCHLD. Tu peux même te contenter de faire un signal(SIGCHLD, SIG_IGN). |
Evidemment c'est plus simple...
Cependant il risque d'y avoir un soucis car dans certains systèmes, la fonction "signal" n'est armée qu'une seule fois et se désarme à la réception du signal. dans d'autres systèmes la fonction reste armée pour les autres signaux. A ce que je sais, le comportement dans un cas ou dans l'autre n'est pas encore normalisé.
Si jamais c'est le premier comportement qui est présent sur le système de bad11, alors seul le premier signal du premier fils sera intercepté et les autres resteront zombies.
Un moyen de se prévenir de cet éventuel problème est de positionner le signal(SIGCHLD) sur une fonction qui ne fait que réarmer le signal, du style
Code :
|
bad11 a écrit : Thanks Sve@r pour cette bonne explication en français et non remplie de mots barbares linuxiens ^^. |
Ils sont pas barbares les mots linuxiens , tu viens de le dire... ils sont L I N U X I E N S
Marsh Posté le 12-10-2004 à 08:12:07
Sve@r a écrit :
|
Nope. Même ça ne marche pas bien. Evidemment, si tu as une mort tous les 40 du mois, ça passera, mais pour tout signal reçu plus d'une fois par seconde, tu t'exposes à de jolis problèmes.
Il faut utiliser sigaction et ses petits frères.
Marsh Posté le 12-10-2004 à 20:06:08
La premiere méthode avec wait et waitpid ne marche pas, rien n'y fait.
J'ai testé SigCHD et ca marche , meme avec un tas de connexion.
Je vous remercie , a une prochaine fois surement pour un petit coup de pouce
Marsh Posté le 11-10-2004 à 20:10:55
Coucou !
Voila je dois développer un programme perso qui est un serveur qui attend des connections sur le port prédéfini et qui envoie un fichier texte au client qui se connecte , puis déconnecte le client.
Le serveur est fait pour ne jamais s'arreter(boucle infinie) et pour marcher en parallele (traiter plusieurs client en meme tps).
Tres scolaire et tres simple en théorie .
Mon probleme :
Je cré un processus fils qui traitera la demande d'un client qui se connecte (avec fork() ).
Mon probleme est que quand je lance mon serveur, chaque processus fils terminé laisse un "zombie" une trace de lui dans la liste des processus.
Il faudrait que le programme principal, donc le pere attende la fin du fils qui traite la demande mais là cela ne serait plus un serveur parallele.
Comment puis je faire? je développe en C sous Linux.