Les processus

mercredi 17 septembre 2008
par  Jerome ROBERT
popularité : 4%

Les processus et mécanismes de base d’Unix

 

I. Définitions et attributs

Un programme est une suite d’instructions stockées dans un fichier
(binaire ou contenant des commandes). Une fois lancé, un programme donne
naissance à une entité appelée processus (un même programme peut
être exécuté simultanément par plusieurs utilisateurs ®
plusieurs processus distincts).

La notion de programme est statique ; celle de processus
est dynamique  : un processus est l’exécution d’un programme.
Il est créé à un certain moment, a une certaine durée de vie, puis meurt.

Un processus est caractérisé par un numéro, son PID. Ce numéro est
unique sur le système à un instant donné.

Un Shell en fonctionnement est un exemple de processus.

L’activité du système se traduit par la présence simultanée de nombreux
processus dans une politique de temps partagé dans laquelle le noyau
gère le partage des ressources ( accès à la mémoire, au(x) processeur(s)
etc... ).

Chaque processus présent dans le système occupe différentes régions en
mémoire. Du point de vue de leur fonctions, on peut distinguer :

  • une zone de texte (code de la commande),
  • une zone de données statiques, contenant les données du
    programme connues dès sa compilation (variables globales ou statiques
    du C par exemple),
  • une pile utilisateur réservée aux variables dynamiques crées
    au moment de l’exécution (variables locales en C),
  • une pile système, utilisée lors de l’exécution de fonctions
    système,
  • une zone de tas réservée à l’allocation dynamique (par
    exemple, la fonction new() en C++),
  • un bloc de contrôle réunissant l’ensemble des informations
    concernant le processus

Une même zone de texte peut-être partagée par plusieurs processus (un tel
programme est qualifié de réentrant). Les autres zones mémoires sont
en revanche propres à un processus.

Du point de vue de l’emplacement physique en mémoire, on distingue :

La zone utilisateur : c’est la zone mémoire que le processus peut
adresser lorsqu’il s’exécute en mode utilisateur, c’est-à-dire tant
qu’il n’exécute pas d’appel-système. Cette région contient les zones
de texte, de pile et de tas
.

La zone système : C’est la zone mémoire supplémentaire que peut
adresser le processeur lorsqu’il est en mode noyau, c’est-à-dire
lorsqu’il exécute un appel-système. Cette zone contient le noyau,
c’est-à-dire le code de tous les appels-système, les tables du système
(i-noeud en mémoire, fichiers ouverts, processus, ...) et la pile
système
de chaque processus (pile allouée aux processus s’exécutant
en mode noyau).

Unix est un système « classique » à mémoire virtuelle. Le noyau
gère un espace mémoire constitué de la mémoire physique et de l’espace de
pagination ( « zone(s) de swap » ).

Un processus en erreur ne peut pas compromettre l’intégrité du système.

En effet, dans cette situation, le noyau met fin au processus via une
interruption ( « signal » ) qui,

dans la plupart des cas, provoque la génération d’un « dump » de l’image
mémoire du processus

sous la forme d’un fichier « core » créé dans le répertoire
courant.

De tels fichiers peuvent ensuite être exploités à l’aide de débogueurs
ou simplement éliminés.

 

II. Les différents état d’un processus :

Un processus a une durée de vie limitée ; voici le cycle de vie type d’un
processus :

 

 

III. Lancement d’un processus

Tous les processus (à l’exception du premier, créé au boot),
sont lancés par un autre processus.

En général, c’est un shell qui lance un nouveau processus
UNIX, selon l’une de deux méthodes suivantes :

 

 

a. Lancement d’un processus en avant plan

Ce mécanisme repose donc sur quatre appels systèmes constituant les
éléments de base de l’interface de programmation système ( en langage C ) :

 

- fork Duplication de processus.

Après le « fork », deux processus exécutent le même code. Il y a
un code retour différent pour chaque processus, leur permettant de s’aiguiller
vers deux endroits respectifs dans la suite du programme.

- exec Mécanisme de recouvrement ( « overlay » ). L’ancien
code est remplacé par un nouveau programme dans le cadre du même
processus. Après un « exec » réussi, on ne revient jamais dans l’ancien
programme.

- wait Attente de la fin d’un processus « fils ». La fin du
processus fils débloque cet appel système et permet de récupérer un
code retour. Il est nécessaire, dans ces schémas de programmation
multi-tâches, d’effectuer, à un moment donné, un « wait » sur les
fils générés pour éviter la création de processus dit « zombies »
( « defunct » ).

- exit Terminaison d’un processus. Libération des
ressources et déblocage d’un éventuel « wait » symétrique avec
propagation d’un code retour.

 

Attributs d’un processus

PID Numéro identifiant le processus ( unique à un instant donné )
PPID  Numéro du processus « parent »
UID Propriétaire.
Par défaut, il s’agit du « login » ayant lancé le programme. Si le programme possède la permission « SUID », le propriétaire du processus est celui du programme.

 

GUID Groupe du propriétaire.
Par défaut, il s’agit du groupe principal du « login ».Si le programme possède la permission « SGID » , le groupe propriétaire du processus est celui du programme.
TTY Terminal de contrôle
Il n’est pas toujours défini ( processus de type « daemon » ). Celui-ci est défini par défaut pour les processus lancés en interactif, il peut aussi être défini par programmation. On précisera son utilité plus loin dans ce chapître ( redirections ).
NICE VALUE  Valeur de priorité de départ.
Cette priorité évolue ensuite au fur et à mesure de l’exécution pour respecter la politique « égalitaire » du temps partagé.
CLASSE  Sur certaines versions, il peut exister d’autres classes de processus que celle, par défaut, du temps partagé.Par exemple, en System V.4, on trouve la classe RT (« Real Time »)qui est plus prioritaire que la classe TS (« Time Sharing ») et dans laquelle les priorités sont fixes.

 

 

 

b. Lancement d’un processus en arrière-plan

Les lancements en arrière-plan (ou background) se
distinguent des lancements en avant plan (ou foreground) par le fait que le
processus père n’attend pas la fin de l’exécution du processus fils pour
continuer à travailler.

 

 

syntaxe : $ cmde &

 

résultat immédiat : [Num d’ordre] PID

résultat en fin d’execution : message du type
terminate ,done , killed ,...

 

 

Exemples : $ sleep 100 &

[1] 4789

$ _

 

 

 

On peut souhaiter lancer un programme sans attendre la fin de
celui-ci.

On utilise le caractère & pour lancer une commande en
arrière-plan.

Le processus créé hérite des descripteurs de fichiers ( entrée, sortie et
erreur ) du processus shell.

Il convient donc d’utiliser les redirections afin d’éviter l’arrivée
périodique de messages ou résultats sur l’écran.

 

$ ls -alR / > resul 2> /dev/null &

[1] 18676

$ ps -fu stage1

UID PID PPID C STIME TTY TIME COMD

stage1 18677 18397 10 12:25:46 pts/2 0:00 ps -fu stage1

stage1 18397 18395 1 09:02:43 pts/2 0:02 -ksh

stage1 18676 18397 46 12:25:36 pts/2 0:07 ls -alR /

$

 

La fin du programme sera visualisée par un message à l’écran lors d’une
entrée clavier.

$ entrée clavier plus tard ...

[1] + Done(2) ls -alR / > resul 2> /dev/null &

$

Mode détaché ( pouvoir se déconnecter )

Le fait de se déconnecter entraîne, par défaut, l’interruption des
processus lancés en arrière-plan.

Ceux-ci reçoivent en effet le signal « SIGHUP » de fin de session.

La commande nohup protège le processus lancé en arrière-plan contre
ce signal et permet ainsi d’en continuer l’exécution même après
déconnexion.

$ nohup ls -alR / > resul 2> /dev/null &

[1] 18692

$

 

Dans ce cas également, il ne faut pas négliger les redirections de la
sortie et de l’erreur.

Si aucune redirection n’est faite, les résultats et erreurs sont dirigés
vers un fichier nohup.out

dans le répertoire de connexion.

$ nohup ls -alR / &

[1] 18707

$ UX:nohup : INFO : Sending output to nohup.out

 

IV. La commande "ps"

 

ps affiche la liste des processus actifs

Attention, la commande ps est l’une des moins standards du monde Unix en ce
qui concerne les options et les informations affichées.

Exemples :

$ ps #affiche les processus associés à votre terminal
PID TTY TIME COMMAND
481 ttyp1 0:00 ps
469 ttyp1 0:00 telnetd
470 ttyp1 0:00 ksh

 

$ ps -f #affiche les processus associés au terminal (avec détails)
UID PID PPID C STIME TTY TIME COMMAND
didier 482 470 5 17:40:33 ttyp1 0:00 ps -f
root 469 147 0 17:36:14 ttyp1 0:00 telnetd
didier 470 469 1 17:36:14 ttyp1 0:00 -ksh
 
$ ps -l #affiche les processus associés au terminal (avec détails)
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME COMD
1 R 204 484 470 5 179 20 539780 16 ttyp1 0:00 ps
1 S 0 469 147 0 154 20 53f900 16 2875b8 ttyp1 0:00 telnetd
1 S 204 470 469 0 158 20 5398c0 55 34cf40 ttyp1 0:00 ksh

$ ps -fl #affiche plus de détails

$ ps -ef | more #affiche tous les processus du système

$ ps -u john #affiche tous les processus appartenant à john

 

Signification des différentes colonnes :

Flag, donnant des indications sur les caractéristiques du process
S Status

Les differents status :

R : RUN actif ou non (élu ou éligible).

W : WAITING (en attente).

T : STOP (suspendu).

S : SLEEPING (endormi).

Z : ZOMBIE (terminé).

PID  Process ID

 

PPID  Parent Process ID
TTY  Terminal
TIME  Temps d’exécution réel
STIME  Start Time (heure ou jour si avant aujourdhui)
C  Utilisé pour le calcul de la priorité.
PRI  Priorité réelle , recalculée en permanence par Unix

 

NI  Nice (Nombre utilisé pour calculer la priorité)
COMD  Commande (Nom du process)

 

 

F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME COMD
1 R root 17298 15651 19 182 20 840900 21 - 10:16:11 pts/0 0:00 ps -fle
1 S root 1080 1 0 156 20 901e00 87 62d000 Apr 22 console 0:00 -sh
1 S root 1094 1 0 156 20 785980 0 62d564 Apr 22 tty0p5 0:00 /usr/sbin/getty -h tty0p5 H
1 S root 1084 1 0 156 20 9ebf00 0 62d114 Apr 22 tty0p1 0:00 /usr/sbin/getty -h tty0p1 H
1 S jerome 13556 13555 0 156 20 856b80 105 607228 09:31:43 ttyp2 0:00 -sh
1 S root 1089 1 0 156 20 a26c80 0 62d228 Apr 22 tty0p2 0:00 /usr/sbin/getty -h tty0p2 H
1 S root 1091 1 0 156 20 8b3c00 0 62d33c Apr 22 tty0p3 0:00 /usr/sbin/getty -h tty0p3 H
1 S root 1092 1 0 156 20 9d9d80 0 62d450 Apr 22 tty0p4 0:00 /usr/sbin/getty -h tty0p4 H
1 S root 15651 15511 2 158 20 98d400 94 4f1100 09:56:42 pts/0 0:00 -sh
1 S root 13555 599 0 154 20 bd5780 5 599080 09:31:42 ttyp2 0:00 telnetd

 

Avec d’autres options, il est possible de sélectionner certaines familles
de processus.

Quelques options System V.4 : 

-e Tous les processus
-t tty Tous ceux contrôlés par le terminal de nom tty
-u login Tous ceux d’un propriétaire donné

$ ps -f -u oracle

UID PID PPID C STIME TTY TIME COMD
oracle 17705 17703 1 17:32:08 pts/3 0:00 -ksh
oracle 17743 1 0 17:32:51 ? 0:00 ora_dbwr_oria
oracle 17744 1 0 17:32:53 ? 0:00 ora_lgwr_oria
oracle 17742 1 0 17:32:49 ? 0:00 ora_pmon_oria
oracle 17750 17705 10 17:34:13 pts/3 0:00 ps -f -u oracle
oracle 17745 1 0 17:32:55 ? 0:02 ora_smon_oria
oracle 17746 1 0 17:32:57 ? 0:00 ora_reco_oria

$

$ ps -ef

UID PID PPID C STIME TTY TIME COMD
root 0 0 0 Nov 25 ? 0:00 sched
root 1 0 0 Nov 25 ? 1:10 /sbin/init
root 2 0 0 Nov 25 ? 0:01 pageout
root 3 0 0 Nov 25 ? 6:56 fsflush
root 4 0 0 Nov 25 ? 0:00 kmdaemon
..............................................
..............................................
root 264 1 0 Nov 25 ? 0:01 /usr/lib/saf/sac -t 300
root 207 1 0 Nov 25 ? 0:01 /usr/X/bin/xdm
root 199 1 0 Nov 25 ? 0:01 /usr/sbin/rpcbind
root 323 317 0 Nov 25 ? 0:00 lpNet
root 271 264 0 Nov 25 ? 0:02 /usr/sbin/inetd
root 317 1 0 Nov 25 ? 0:00 /usr/lib/lpsched
root 300 1 0 Nov 25 ? 1:30 /usr/sbin/cron
stage1 17785 17771 19 17:38:54 pts/2 0:00 ps -ef
stage1 17771 17769 0 17:38:40 pts/2 0:00 -ksh
$

 

Le processus de numéro 0 correspond à l’exécution du noyau
Unix.

Ce processus génère des processus « fils » annexes de numéros >= 2 .

Le processus de numéro 1 correspond au programme init qui est
à l’origine de tous les autres processus présents, par la suite, sur le
système.

Le paramétrage du programme « init » constitue une des tâches importantes d’administration.

 

A chaque service système, correspond un certain nombre de processus de type
« daemon » :

- lpsched Spouleur

- cron Planificateur de travaux

- inetd, rpcbind Démons essentiels dans les activités « réseau »

etc...

 


V. INTERRUPTION DES PROCESSUS - SIGNAUX

a. Notion de signal

Un signal est une interruption émise vers un processus qui, par
défaut, est éliminé.

Cependant, le programme a pu être prévu pour ignorer certaines
interruptions ou

associer un traitement à la réception d’un signal donné.

Les signaux peuvent être déclenchés, suivant les cas, par une action de l’utilisateur
au clavier,

par programme, ou par le noyau souhaitant éliminer un processus en erreur.

Certains signaux ont pour effet de générer un fichier « core » dans
le répertoire courant.

Ce fichier contient l’image mémoire du processus au moment de l’interruption
et

peut être examiné à l’aide d’un débogueur.

Les noms des signaux Unix sont standardisés au niveau des interfaces de
programmation.

Leur numéro interne peut, par contre, varier selon les implémentations.

Pour les signaux les plus fréquents et ceux qui concernent l’utilisateur,
les numéros sont standards.

 

Signaux usuels

SIGHUP  Fin de session. A la déconnexion du shell, ce signal est envoyé à tous les processus de même terminal de contrôle.
SIGINT  2  Interruption clavier ( touche paramétrable ) ( touche Break ou Del ou Suppr ou Ctrl c ... )
SIGQUIT  3  Interruption clavier générant un fichier « core » ( touche Ctrl \ )
SIGTERM  15  Terminaison normale. Ce signal est généré via la commande « kill » ( voir ci-après ).Il peut être capté par le programme pour, par exemple,opérer un nettoyage d’objets système avant de se terminer.
SIGKILL  9  Terminaison brutale.Ce signal ne peut pas être capté par le programme,il provoque un arrêt immédiat de celui-ci.

 

Liste des signaux sous Solaris 8

kill -l

1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL

5) SIGTRAP 6) SIGABRT 7) SIGEMT 8) SIGFPE

9) SIGKILL 10) SIGBUS 11) SIGSEGV 12) SIGSYS

13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGUSR1

17) SIGUSR2 18) SIGCHLD 19) SIGPWR 20) SIGWINCH

21) SIGURG 22) SIGIO 23) SIGSTOP 24) SIGTSTP

25) SIGCONT 26) SIGTTIN 27) SIGTTOU 28) SIGVTALRM

29) SIGPROF 30) SIGXCPU 1) SIGXFSZ 32) SIGWAITING

33) SIGLWP 34) SIGFREEZE 35) SIGTHAW 36) SIGCANCEL

37) SIGLOST

 

 

 

b. arrêter un processus

La condition nécessaire pour éliminer un processus est d’émettre le
signal depuis un processus

de même propriétaire ou depuis un processus « super-user » ( login « root »
).

 

Si cette condition est remplie et que l’envoi d’un signal donné n’est
pas efficace, cela signifie

sans doute que le programme correspondant au processus visé a prévu d’ignorer
cette interruption.

Dans ce cas, l’envoi du signal SIGKILL ( numéro 9 ) sera le dernier
recours.

 

On conseillera de n’utiliser le signal 9 que si les autres signaux ( 2, 3 ,
15 ) ont échoué.

Cette remarque peut être importante dans le cas notamment de processus
créant des objets système

( mémoire partagée, sémaphores, etc... ) qui ne sont pas implicitement
libérés.

kill -s nomsignal PID [PID .... PID] envoie un signal
(généralement mortel) à un/des

processus

 

Exemples :

$ find / -name passwd -print 2> /dev/null &

[1] 1256

$ kill -s KILL 1256 tue irrémédiablement le processus de PID 8569

[1] +killed find ... &

$ kill 8569 envoi par défaut le signal TERM

 

Remarque : kill -l affiche la ligne des signaux que l’on peut
envoyer.

NB : On ne peut envoyer un signal qu’aux processus qui nous
appartiennent. Seul root (le Super User) peut envoyer un signal vers n’importe
quel processus.

Mise en pratique

- Si le processus est attaché au terminal,

Interruptions clavier ( signal 2 ou signal 3 )

- Si échec,

Connexion sur un autre terminal ( ou une autre fenêtre « xterm » ) sous
le même « login »

Liste des processus ( commande ps ) pour visualiser le PID du
processus concerné

Commande kill

Cette commande envoie un signal vers un processus dont on donne le PID
en argument.

Le numéro du signal se donne via l’option ( sans option, on envoie le
signal 15 ).

kill pid ( émission du signal 15 )

ou

kill -9 pid ( émission du signal 9 )

 

 

Cas concret : "Déplanter" le terminal d’un
autre utilisateur :

 

Terminal TheBest (non planté ) Terminal GrosNul (planté)

 

 

 

c. Traitement
d’un signal
 : la commande
trap

Lorsque qu’un processus reçoit un signal , son déroulement normal est
interrompu pour effectuer un traitement par défaut (voir tableau plus haut).

Pour la plupart des signaux (numéros) existants , il est possible de
spécifier un bloc de traitements spécifiques qui sera exécuté à la place du
traitement par défaut. Ceci se fait grace à la commande trap  :

 

trap ’cmdeA ;cmdeB,.... ;cmdeZ’ signo1 [signo2 .... signoN]

 

NB : Une fois que le signal a été traité (bloc trap exécuté) , le
processus reprend son cours normal à l’endroit où il a été dérouté.

Un processus peut choisir d’ignorer certains signaux : il se comporte alors
comme si le signal n’avait jamais été reçu (aucun déroutement) :

trap ’’ signo1 [signo2 .... signoN]

Ignorer certains signaux est une opération intéressante dans le cas où
l’on ne désire pas être interrompu pendant l’exécution d’une portion de code
critique. Il est ensuite possible de restituer les traitements par défaut
grâce à la syntaxe suivante :

trap - signo1 [signo2 ...]

Exemple :

trap ’rm /tmp/fictemp ; exit’ 1 2 3 15 # suppression du fichier #
temporaire fictemp

trap ’’ 1 2 3 15

# section de code très importante

trap - 1 2 3 15

# section ordinaire

La commande trap utilisée sans argument donne la liste des signaux
détournés et l’action correspondante.

 

d. PROCESSUS Séquentiels

Il est possible de taper plusieurs commandes sur la même ligne, notamment
dans une procédure shell, via le caractère  ; ( point-virgule ) .

Les processus sont indépendants, ils s’exécutent l’un après l’autre
et il n’y a aucune communication d’informations entre eux.

Le mécanisme peut être intéressant pour réaliser des redirections
globales via les parenthèses
.

 

Exemples

$ date ; ls ; who

Sun Dec 24 23:59 1995
fic1 fic2 fic3
stage1 tty00 Dec 24 12:30
stage2 tty01 Dec 24 16:12

$

$ who ; ls > toto Seule la deuxième commande est redirigée

stage1 tty00 Dec 24 12:30
stage2 tty01 Dec 24 16:12
$ cat toto
fic1
fic2
fic3

$

$ ( who ; ls ) > toto Redirection global

$ cat toto

stage1 tty00 Dec 24 12:30
stage2 tty01 Dec 24 16:12
fic1
fic2
fic3
$

 

Le signe ">" sera vu dans le module "redirection"

 

d. PROCESSUS EN PARALLELE ( PIPELINE )

Le « pipeline » est un mécanisme de communication entre processus
s’exécutant en parallèle.

Il correspond au caractère | intercalé entre les différentes
commandes mises en jeu.

 

Objectif du mécanisme

OBTENIR UN RESULTAT FINAL A PARTIR DE COMMANDES ELEMENTAIRES

QUI PROPAGENT LEURS RÉSULTATS INTERMEDIAIRES

 

Le principe est le suivant :

- La sortie standard d’un premier processus est redirigée vers un
fichier temporaire ( « pipe » ou tube ). Ce fichier se comporte comme une file ( FIFO ).

- L’entrée standard du processus suivant est redirigée vers cette
même file.

- Le système assure la synchronisation de ces processus qui s’exécutent
« en même temps ».

 

Ce mécanisme n’est pas limité en nombre de commandes mises en jeu. Un tube est créé pour chaque couple de commandes.

La quantité de données échangées n’est pas non plus limitée. Le traitement a lieu aussi longtemps que le premier processus alimente le
« pipe » .

La création des tubes et les redirections sont effectuées par le shell.


Grâce au principe des fichiers standards, les commandes s’utilisent sans
changement.

 

 

Exemples simples


ls -al / | more Consultation écran par écran du résultat de la
commande ls

La commande « more » n’ayant pas d’argument, elle lit son entrée
standard.

 

who | wc -l Nombre d’utilisateurs connectés

La commande « who » écrit sur sa sortie standard une ligne par utilisateur.

La commande « wc -l » compte les lignes fournies sur son entrée standard.

 

Un « pipeline » n’est pas limité à deux commandes.

 

$ ls -l

total 4
drwxr-xr-x 3 stage1 stage 96 Dec 13 15:41 rep
-rw-r—r— 1 stage1 stage 16 Dec 14 11:21 titi
-rw-r—r— 1 stage1 stage 0 Dec 15 10:33 toto
-rw-r—r— 1 stage1 stage 15 Dec 14 11:21 tutu
$
$ ls -l | tail +2

drwxr-xr-x 3 stage1 stage 96 Dec 13 15:41 rep
-rw-r—r— 1 stage1 stage 16 Dec 14 11:21 titi
-rw-r—r— 1 stage1 stage 0 Dec 15 10:33 toto
-rw-r—r— 1 stage1 stage 15 Dec 14 11:21 tutu
$
$ ls -l | tail +2 | head -3

drwxr-xr-x 3 stage1 stage 96 Dec 13 15:41 rep
-rw-r—r— 1 stage1 stage 16 Dec 14 11:21 titi
-rw-r—r— 1 stage1 stage 0 Dec 15 10:33 toto

$

 

Mémoriser les résultats intermédiaires

La commande tee permet de mémoriser les résultats intermédiaires.

Elle opère une duplication de la sortie standard vers un fichier.

L’option -a permet une utilisation en mode « ajout ».

 

$ ls -l | tee zorro | tail +2 | wc -l

4
$ cat zorro

total 4
drwxr-xr-x 3 stage1 stage 96 Dec 13 15:41 rep
-rw-r—r— 1 stage1 stage 16 Dec 14 11:21 titi
-rw-r—r— 1 stage1 stage 0 Dec 15 10:33 toto
-rw-r—r— 1 stage1 stage 15 Dec 14 11:21 tutu
$

 

$ echo bonjour cher ami | tee zorro | wc -w | tee -a zorro

3
$ cat zorro

bonjour cher ami
3
$

L’entrée standard du premier processus et la sortie standard du dernier ne
sont pas redirigées

vers les tubes.

Elles restent disponibles pour une redirection classique.


Statistiques

Dernière mise à jour

mercredi 5 juillet 2017

Publication

264 Articles
Aucun album photo
Aucune brève
6 Sites Web
2 Auteurs

Visites

173 aujourd’hui
242 hier
538279 depuis le début
2 visiteurs actuellement connectés