Le canal est un fichier ouvert dans un système de fichiers dans le noyau et n'est pas accessible en tant que fichier normal sur le disque. Il est automatiquement mis en mémoire tampon uniquement jusqu'à une certaine taille et finira par se bloquer lorsqu'il sera plein. Contrairement aux fichiers provenant de blocs-périphériques, les canaux se comportent très comme des périphériques de caractères, et ne prennent donc généralement pas en charge lseek()
et les données qui en sont lues ne peuvent pas être lues à nouveau comme vous le feriez avec un fichier normal.
La chaîne ici est un fichier normal créé dans un système de fichiers monté. Le shell crée le fichier et conserve son descripteur tout en supprimant immédiatement son seul lien vers le système de fichiers (et donc en le supprimant) avant qu'il n'écrive / ne lise un octet dans / depuis le fichier. Le noyau conservera l'espace requis pour le fichier jusqu'à ce que tous les processus libèrent tous les descripteurs pour celui-ci. Si l'enfant qui lit à partir d'un tel descripteur a la capacité de le faire, il peut être rembobiné lseek()
et relu.
Dans les deux cas, les jetons <<<
et |
représentent les descripteurs de fichiers et pas nécessairement les fichiers eux-mêmes. Vous pouvez avoir une meilleure idée de ce qui se passe en faisant des choses comme:
readlink /dev/fd/1 | cat
...ou...
ls -l <<<'' /dev/fd/*
La différence la plus significative entre les deux fichiers est que la chaîne ici / doc est à peu près une affaire tout à la fois - le shell y écrit toutes les données avant d'offrir le descripteur de lecture à l'enfant. D'un autre côté, le shell ouvre le canal sur les descripteurs appropriés et bifurque les enfants pour gérer ceux du canal - et il est donc écrit / lu simultanément aux deux extrémités.
Ces distinctions, cependant, ne sont généralement vraies. Pour autant que je sache (ce qui n'est pas vraiment si loin), cela est vrai à peu près tous les shell qui traitent la <<<
raccourci ici-chaîne pour <<
une redirection ici-document à la seule exception de yash
. yash
, busybox
, dash
Et d' autres ash
variantes ont tendance à revenir ici-documents avec des tuyaux, cependant, et donc dans ces coquilles il y a vraiment très peu de différence entre les deux , après tout.
Ok - deux exceptions. Maintenant que j'y pense, ksh93
ne fait pas du tout de tuyau |
, mais gère plutôt toute l'entreprise avec des sockets - bien qu'il fasse un fichier tmp supprimé <<<*
comme la plupart des autres. De plus, il ne place les sections séparées d'un pipeline dans un environnement de sous - shell qui est une sorte d'euphémisme POSIX car au moins il agit comme un sous-shell , et donc ne fait même pas les fourches.
Le fait est que les résultats de référence de @ PSkocik (ce qui est très utile) peuvent varier considérablement pour de nombreuses raisons, et la plupart d'entre eux dépendent de l'implémentation. Pour la configuration du document ici, les facteurs les plus importants seront le ${TMPDIR}
type de système de fichiers cible et la configuration / disponibilité actuelle du cache, et encore plus la quantité de données à écrire. Pour le tuyau, ce sera la taille du processus shell lui-même, car des copies sont faites pour les fourches requises. De cette façon, bash
c'est terrible lors de la configuration du pipeline (pour inclure les substitutions de $(
commandes )
) - car il est grand et très lent, mais ksh93
cela ne fait pratiquement aucune différence.
Voici un autre petit extrait de shell pour montrer comment un shell se divise en sous-shell pour un pipeline:
pipe_who(){ echo "$$"; sh -c 'echo "$PPID"'; }
pipe_who
pipe_who | { pipe_who | cat /dev/fd/3 -; } 3<&0
32059 #bash's pid
32059 #sh's ppid
32059 #1st subshell's $$
32111 #1st subshell sh's ppid
32059 #2cd subshell's $$
32114 #2cd subshell sh's ppid
La différence entre ce que pipe_who()
rapporte un appel en pipeline et le rapport d'une exécution dans le shell actuel est due au comportement spécifié d' un (
sous-shell )
de réclamer le pid du shell parent $$
lorsqu'il est développé. Bien que les bash
sous- $$
coquilles soient définitivement des processus distincts, le paramètre spécial de coquille n'est pas une source fiable de ces informations. Pourtant, le shell enfant du sous- sh
shell ne refuse pas de le signaler avec précision $PPID
.
Rien ne remplace le benchmarking:
Et pour une plus grande quantité de données:
Il semblerait que la version pipe ait un coût d'installation plus élevé mais est finalement plus efficace.
la source
echo foo >/dev/shm/1;cat /dev/shm/1 >/dev/null
semblait être rapide dans les deux cas ...echo "$longstring"
ou<<<"$longstring"
serait être modifié pour une efficacité et avec des chaînes courtes, l' efficacité n'a pas d' importance beaucoup de toute façon.cat <(echo foo) >/dev/null
est plus rapide queecho foo | cat >/dev/null
.