Comment un processus peut-il trouver les pids de processus avec lesquels il communique via un tube?

Disons que j’ai le pipeline suivant:

$ generator_process | filter_process | storage_process 

Est-ce que filter_process peut trouver le pid de generator_process et storage_process ? Si c’est le cas, comment? Si non, pourquoi?

Plus généralement, comment un processus peut-il trouver les pids de processus avec lesquels il communique via un tube?

Je recherche un moyen portable (POSIX) de le faire, mais si cela nécessite des trucs spécifiques à une plate-forme, une solution Linux est ce que je recherche. Je suppose qu’une réponse dans C donnerait le plus de détails, mais si cela implique le shell, je cherche une solution bash.

Supposons que je puisse changer filter_process mais generator_process et storage_process sont des programmes que je n’ai aucune possibilité ou envie de modifier (ils pourraient être des outils Unix standard que je ne veux pas manipuler). En outre, les emballer dans des scripts qui écrivent leurs pids sur le disque n’est pas la solution que je recherche.

Notez qu’une extrémité d’un tube peut être ouverte dans plusieurs processus simultanément (via fork() ou sendmsg de descripteur de fichier sendmsg ). Vous ne pouvez donc pas obtenir une seule réponse.

Sous Linux, vous pouvez examiner /proc//fd pour voir ce que fds est ouvert (vous devez être root ou le même uid que le processus cible). Je viens de courir grep a | grep b grep a | grep b et a obtenu la sortie suivante:

 /proc/10442/fd: total 0 dr-x------ 2 nneonneo nneonneo 0 Sep 20 02:19 . dr-xr-xr-x 7 nneonneo nneonneo 0 Sep 20 02:19 .. lrwx------ 1 nneonneo nneonneo 64 Sep 20 02:19 0 -> /dev/pts/5 l-wx------ 1 nneonneo nneonneo 64 Sep 20 02:19 1 -> pipe:[100815116] lrwx------ 1 nneonneo nneonneo 64 Sep 20 02:19 2 -> /dev/pts/5 /proc/10443/fd: total 0 dr-x------ 2 nneonneo nneonneo 0 Sep 20 02:19 . dr-xr-xr-x 7 nneonneo nneonneo 0 Sep 20 02:19 .. lr-x------ 1 nneonneo nneonneo 64 Sep 20 02:19 0 -> pipe:[100815116] lrwx------ 1 nneonneo nneonneo 64 Sep 20 02:19 1 -> /dev/pts/5 lrwx------ 1 nneonneo nneonneo 64 Sep 20 02:19 2 -> /dev/pts/5 

Donc, il s’ensuit qu’en utilisant readlink sur le fd de votre propre processus, suivi de readlink sur d’autres processus que vous possédez, vous pouvez déterminer qui se trouve de l’autre côté du canal.

Une manière farfelue de découvrir (à partir d’un script Bash) quels pids et fds sont connectés à un canal particulier:

 get_fd_target() { pid=$1 fd=$2 readlink /proc/$pid/fd/$fd } find_fd_target() { target=$1 for i in /proc/*/fd/*; do if [ "`readlink $i`" == "$target" ]; then echo $i fi done } 

Ensuite, si vous voulez savoir quelles fds sur le système sont connectées à stdin de votre script:

 find_fd_target `get_fd_target $$ 0`