Pourquoi $$ renvoie-t-il le même identifiant que le processus parent?

160

J'ai un problème avec Bash et je ne sais pas pourquoi.
Sous coquille, j'entre:

echo $$    ## print 2433
(echo $$)  ## also print 2433
(./getpid) ## print 2602

"getpid" est un programme C pour obtenir le pid actuel, comme:

   int main() {
    printf("%d", (int)getpid());
    return 0;
   }

Ce qui me trouble, c'est que:

  1. Je pense que "(commande)" est un sous-processus (ai-je raison?), Et je pense que son pid devrait être différent de son pid parent, mais ils sont les mêmes, pourquoi ...
  2. quand j'utilise mon programme pour afficher pid entre parenthèses, le pid qu'il montre est différent, n'est-ce pas?
  3. '$$' est-il quelque chose comme une macro?

Pouvez-vous m'aider?

ruanhao
la source
8
Notez que getpidcela afficherait un ID de processus différent même s'il n'était pas exécuté dans un sous-shell.
chepner
1
@Marian echo $$ $BASHPID ; ( echo $$ $BASHPID )démontre que c'est le cas. Les crochets ronds créent un sous-shell. Les instructions peuvent changer les valeurs des variables et le shell parent ne doit pas voir ces changements. Ceci est implémenté comme une fork()opération.
Ben le

Réponses:

223

$$est défini pour renvoyer l'ID de processus du parent dans un sous-shell; depuis la page de manuel sous "Paramètres spéciaux":

$ S'étend à l'ID de processus du shell. Dans un sous-shell (), il s'étend à l'ID de processus du shell actuel, et non au sous-shell.

Dans bash4, vous pouvez obtenir l'ID de processus de l'enfant avec BASHPID.

~ $ echo $$
17601
~ $ ( echo $$; echo $BASHPID )
17601
17634
chepner
la source
17
"parent" est un peu trompeur (du moins c'était pour moi), c'est en fait le shell "top level". Par exemple: echo $$; (echo $$; (echo $$))fait écho trois fois au même pid
Martin Bouladour
1
Droite; J'aurais dû dire que la valeur est héritée d'un shell parent (qui a hérité de sa valeur de son parent, etc.). Le shell de niveau supérieur le définit initialement, plutôt que d'hériter de son processus parent (non-shell).
chepner
$ Expands to the process ID of the shell est-ce que c'est tho? echo $fait juste écho au littéral $.
Alexander Mills
@AlexanderMills Eh bien, oui; $à lui seul, ce n’est pas une expansion des paramètres. La page de manuel fait référence au nom du paramètre spécial, qui est $; il ne prétend pas que $seul se développe.
chepner
Ok, honnêtement, je n'ai aucune idée de ce que cela signifie, mais echo $BASHPIDfonctionne en bash 4 et 5 (mais pas en version 3.2.57 sur MacOS)
Alexander Mills
81

Vous pouvez utiliser l'un des éléments suivants.

  • $! est le PID du dernier processus en arrière-plan.
  • kill -0 $PID vérifie s'il est toujours en cours d'exécution.
  • $$ est le PID du shell actuel.
fou
la source
2
La deuxième puce ne devrait-elle pas être kill -0 $!si nous parlons de processus d'arrière-plan? PIDn'est défini sur rien par défaut.
Isaac Freeman
26
  1. Les parenthèses invoquent un sous - shell dans Bash . Comme il ne s'agit que d'un sous-shell, il peut avoir le même PID - cela dépend de la mise en œuvre.
  2. Le programme C que vous appelez est un processus séparé, qui a son propre PID unique - peu importe qu'il soit dans un sous-shell ou non.
  3. $$est un alias dans Bash du PID de script courant . Voir les différences entre $$et $BASHPIDici , et juste au-dessus de la variable supplémentaire $BASH_SUBSHELLqui contient le niveau d'imbrication.
Niels Keurentjes
la source
4

Essayez getppid()si vous voulez que votre programme C imprime le PID de votre shell.

Alex
la source
2

Si vous demandiez comment obtenir le PID d'une commande connue, cela ressemblerait à quelque chose comme ceci:

Si vous aviez émis la commande ci-dessous #La commande émise était ***

dd if = / dev / diskx of = / dev / disky


Ensuite, vous utiliseriez:

PIDs=$(ps | grep dd | grep if | cut -b 1-5)

Ce qui se passe ici, c'est que tous les caractères uniques nécessaires sont redirigés vers un champ et que ce champ peut être renvoyé en utilisant

echo $ PID

Don-Pierre Halfaway
la source
2

cette façon unique d'obtenir un pid correct

pid=$(cut -d' ' -f4 < /proc/self/stat)

même gentil travaillé pour le sous

SUB(){
    pid=$(cut -d' ' -f4 < /proc/self/stat)
    echo "$$ != $pid"
}

echo "pid = $$"

(SUB)

vérifier la sortie

pid = 8099
8099 != 8100
ARTEM LAPKIN
la source
Bonne idée, mais cela ne vous donnera-t-il pas le pid de la fourche que le shell a exécutée pour capturer la sortie de coupe? Si je l'exécute deux fois, une fois avec echo $ (...) et une fois sans, alors j'obtiens des réponses différentes.
Martin Dorey