Perché non riesco a leggere / dev / stdout con un editor di testo?


9

Ho appena iniziato a imparare come Everything Is A File TM su Linux, il che mi ha fatto chiedere cosa succederebbe se leggessi letteralmente da / dev / stdout:

$ cat /dev/stdout 
^C
$ tail /dev/stdout 
^C

( ^CSto uccidendo il programma dopo che si blocca).

Quando provo con vim, ricevo il messaggio impensabile: "/ dev / stdout" non è un file. Gasp!

Quindi cosa dà, perché ricevo blocchi o messaggi di errore quando provo a leggere questi "file"?


1
Ciò che vim considera un file e cosa si intende per "tutto è un file" (nessun marchio associato) in * nix non sono la stessa cosa. Vedi ad es. # 1 e # 2 .
Riccioli d'oro

Risposte:


11

perché sto ricevendo dei problemi?

Non stai ricevendo "blocchi" da cat(1)e tail(1), stanno solo bloccando in lettura. cat(1)attende l'input e lo stampa non appena viene visualizzata una riga completa:

$ cat /dev/stdout
foo
foo
bar
bar

Qui ho digitato fooEnterbarEnterCTRL- D.

tail(1)attende l'input e lo stampa solo quando è in grado di rilevare EOF:

$ tail /dev/stdout
foo
bar
foo
bar

Qui ho digitato di nuovo fooEnterbarEnterCTRL- D.

o messaggi di errore

Vim è l'unico che ti dà un errore. Lo fa perché corre stat(2) contro /dev/stdoute scopre che non ha il S_IFREGbit impostato.

/dev/stdoutè un file, ma non un file normale . In effetti, c'è un po 'di danza nel kernel per dargli una voce nel filesystem. Su Linux:

$ ls -l /dev/stdout
lrwxrwxrwx 1 root root 15 May  8 19:42 /dev/stdout -> /proc/self/fd/1

Su OpenBSD:

$ ls -l /dev/stdout
crw-rw-rw-  1 root  wheel   22,   1 May  7 09:05:03 2015 /dev/stdout

Su FreeBSD:

$ ls -l /dev/stdout
lrwxr-xr-x  1 root  wheel  4 May  8 21:35 /dev/stdout -> fd/1

$ ls -l /dev/fd/1
crw-rw-rw-  1 root  wheel  0x18 May  8 21:35 /dev/fd/1

5

(Quasi) tutto è un file ma non tutto è un file normale . Non ha senso chiamare un editor di testo su qualcosa che è un file speciale come una directory, un socket di rete, una porta seriale, ecc.

Il file /dev/stdoutpuò essere una delle varie cose a seconda della variante unix:

  • un file "speciale", in genere un dispositivo a caratteri;
  • un collegamento simbolico "magico" che punta al file che il processo che accede ad esso ha aperto su questo descrittore;
  • un collegamento simbolico a uno dei precedenti.

In ogni caso, l'apertura /dev/stdoute file simili creano un nuovo descrittore di file associato allo stesso file che l'applicazione ha già aperto sul descrittore di file 1. "Output standard" significa descrittore di file 1, ed è solo una convenzione che questo descrittore di file viene utilizzato per l'output: al kernel non importa.

Quando si esegue un programma in un terminale, tutti e tre i descrittori standard (0 = input standard, 1 = output standard, 2 = errore standard) vengono aperti sul dispositivo terminale. La lettura da quel dispositivo restituisce i caratteri digitati dall'utente e la scrittura su quel dispositivo visualizza il testo nella finestra del terminale. (Non esiste un modo standard, dato un dispositivo terminale, per leggere l'output che mostra o per iniettare l'input in esso.)

Quando esegui cat /dev/stdout, questo fa esattamente la stessa cosa di cat /dev/stdino cat /dev/stderr, perché questi tre descrittori di file sono collegati allo stesso file: dice catdi leggere dal terminale. Ecco cosa catfa anche senza alcun argomento.

Se hai eseguito cat /dev/stdout >foo, /dev/stdoutfarebbe riferimento al file foo- quel comando è equivalente a cat foo >foo. A seconda catdell'implementazione, potrebbe fuoriuscire un errore (la versione GNU si lamenta che "il file di input è un file di output") o potrebbe non fare nulla perché legge dal file foovuoto ( >fooappena troncato). Con una versione catche non rileva questo caso speciale, se foonon è vuoto, cat /dev/stdout >>fooo l'equivalente cat foo >>fooaggiungerebbe il contenuto del file a se stesso indefinitamente.

Quando corri vim /dev/stdout, si lamenta perché non sa come modificare un terminale (non ha proprio senso).


2

cate tailsono alla ricerca di contenuti opzionali seguiti da una fine del file. /dev/stdoutrimane aperto, in modo cate tailsolo continuare a cercare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.