Je viens de commencer à apprendre comment Everything Is A File TM sur Linux, ce qui m'a fait me demander ce qui se passerait si je lisais littéralement depuis / dev / stdout:
$ cat /dev/stdout
^C
$ tail /dev/stdout
^C
(C'est ^C
moi qui tue le programme après qu'il se soit bloqué).
Lorsque j'essaye vim
, j'obtiens le message impensable: "/ dev / stdout" n'est pas un fichier. Haleter!
Alors qu'est-ce qui donne, pourquoi est-ce que j'obtiens des blocages ou des messages d'erreur quand j'essaye de lire ces "fichiers"?
Réponses:
Vous n'obtenez pas de "raccrochages"
cat(1)
ettail(1)
ils bloquent simplement la lecture.cat(1)
attend l'entrée et l'imprime dès qu'il voit une ligne complète:Ici, j'ai tapé
foo
Enterbar
EnterCTRL- D.tail(1)
attend l'entrée et l'imprime uniquement lorsqu'il peut détecterEOF
:Ici, j'ai tapé à nouveau
foo
Enterbar
EnterCTRL- D.Vim est le seul qui vous donne une erreur. Il fait cela parce qu'il est
stat(2)
contre/dev/stdout
, et il trouve que leS_IFREG
bit n'est pas défini./dev/stdout
est un fichier, mais pas un fichier normal . En fait, il y a de la danse dans le noyau pour lui donner une entrée dans le système de fichiers. Sous Linux:Sur OpenBSD:
Sur FreeBSD:
la source
(Presque) tout est un fichier mais tout n'est pas un fichier normal . Cela n'a pas de sens d'appeler un éditeur de texte sur quelque chose qui est un fichier spécial tel qu'un répertoire, une prise réseau, un port série, etc.
Le fichier
/dev/stdout
peut être une ou plusieurs choses selon la variante unix:Dans tous les cas, l'ouverture de
/dev/stdout
fichiers similaires crée un nouveau descripteur de fichier associé au même fichier que l'application a déjà ouvert sur le descripteur de fichier 1. «Sortie standard» signifie le descripteur de fichier 1, et c'est seulement une convention que ce descripteur de fichier est utilisé pour la sortie - le noyau s'en fiche.Lorsque vous exécutez un programme dans un terminal, les trois descripteurs standard (0 = entrée standard, 1 = sortie standard, 2 = erreur standard) sont ouverts sur le terminal. La lecture à partir de ce périphérique renvoie des caractères saisis par l'utilisateur et l'écriture sur ce périphérique affiche du texte dans la fenêtre du terminal. (Il n'existe aucun moyen standard, étant donné un périphérique terminal, de lire la sortie qu'il affiche ou d'y injecter une entrée.)
Lorsque vous exécutez
cat /dev/stdout
, cela fait exactement la même chose quecat /dev/stdin
orcat /dev/stderr
, car ces trois descripteurs de fichiers sont connectés au même fichier: il indiquecat
de lire à partir du terminal. C'est cecat
que fait sans argument aussi.Si vous couriez
cat /dev/stdout >foo
, alors vous vous/dev/stdout
référez au fichierfoo
- cette commande est équivalente àcat foo >foo
. En fonction de l'cat
implémentation, il peut soit sortir une erreur (la version GNU se plaint que «le fichier d'entrée est un fichier de sortie»), soit ne rien faire car il lit le fichierfoo
vide (>foo
juste tronqué). Avec une versioncat
qui ne détecte pas ce cas spécial, sifoo
n'est pas vide, alorscat /dev/stdout >>foo
ou l'équivalentcat foo >>foo
ajouterait le contenu du fichier à lui-même indéfiniment.Lorsque vous exécutez
vim /dev/stdout
, il se plaint car il ne sait pas comment éditer un terminal (cela n'a tout simplement pas de sens).la source
cat
ettail
recherchent un contenu facultatif suivi d'une fin de fichier./dev/stdout
reste ouvert, donccat
ettail
juste continuer à chercher.la source