Dlaczego nie mogę odczytać / dev / stdout za pomocą edytora tekstu?

9

Właśnie zacząłem uczyć się, jak Everything Is A File TM w systemie Linux, co sprawiło, że zastanawiałem się, co by się stało, gdybym dosłownie czytał z / dev / stdout:

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

(To ^Cja zabijam program po jego zawieszeniu).

Kiedy próbuję vim, pojawia się nie do pomyślenia komunikat: „/ dev / stdout” nie jest plikiem. Łapanie tchu!

Co więc daje, dlaczego dostaję zawieszanie się lub komunikaty o błędach, gdy próbuję odczytać te „pliki”?

użytkownik1717828
źródło
1
To, co vim uważa za plik i co oznacza „wszystko jest plikiem” (brak powiązanego znaku towarowego) w * nix, nie jest tym samym. Zobacz np. Nr 1 i nr 2 .
Złotowłosa

Odpowiedzi:

11

dlaczego dostaję rozłączenia

Nie dostajesz „zawieszania się” od cat(1)i tail(1), one po prostu blokują się podczas odczytu. cat(1)czeka na dane wejściowe i drukuje je, gdy tylko zobaczy pełny wiersz:

$ cat /dev/stdout
foo
foo
bar
bar

Tutaj wpisałem fooEnterbarEnterCTRL- D.

tail(1)czeka na dane wejściowe i drukuje je tylko wtedy, gdy może wykryć EOF:

$ tail /dev/stdout
foo
bar
foo
bar

Tutaj Wpisałem ponownie fooEnterbarEnterCTRL- D.

lub komunikaty o błędach

Vim jest jedynym, który daje ci błąd. Robi to, ponieważ działa stat(2) przeciwko /dev/stdouti stwierdza, że ​​nie ma S_IFREGustawionego bitu.

/dev/stdoutto plik, ale nie zwykły plik. W rzeczywistości jest trochę tańca w jądrze, aby dać mu wpis w systemie plików. W systemie Linux:

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

Na OpenBSD:

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

Na 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
lcd047
źródło
5

(Prawie) wszystko jest plikiem, ale nie wszystko jest zwykłym plikiem. Nie ma sensu wywoływać edytora tekstu na czymś, co jest plikiem specjalnym, takim jak katalog, gniazdo sieciowe, port szeregowy itp.

Plik /dev/stdoutmoże być jedną z kilku rzeczy w zależności od wariantu unix:

  • plik „specjalny”, zwykle urządzenie znakowe;
  • „magiczny” symboliczny link, który wskazuje na plik, który proces uzyskujący dostęp do niego otworzył na tym deskryptorze;
  • symboliczny link do jednego z powyższych.

W każdym razie otwieranie /dev/stdouti podobne pliki tworzą nowy deskryptor pliku powiązany z tym samym plikiem, który aplikacja już otworzyła na deskryptorze pliku 1. „Standardowe wyjście” oznacza deskryptor pliku 1 i jest to tylko konwencja, że ​​ten deskryptor pliku jest używany dla danych wyjściowych - jądro nie ma znaczenia.

Po uruchomieniu programu w terminalu wszystkie trzy standardowe deskryptory (0 = standardowe wejście, 1 = standardowe wyjście, 2 = standardowy błąd) są otwierane na urządzeniu końcowym. Odczytywanie z tego urządzenia zwraca znaki wpisane przez użytkownika, a pisanie na tym urządzeniu wyświetla tekst w oknie terminala. (Nie ma standardowego sposobu, biorąc pod uwagę urządzenie końcowe, odczytania wyświetlanego wyjścia lub wstrzyknięcia do niego danych wejściowych).

Po uruchomieniu cat /dev/stdoutdziała dokładnie tak samo jak cat /dev/stdinlub cat /dev/stderr, ponieważ te trzy deskryptory plików są podłączone do tego samego pliku: nakazuje catodczyt z terminala. Właśnie tocat bez argumentu.

Jeśli uruchomiłeś cat /dev/stdout >foo, to /dev/stdoutodniósłby się do pliku foo- to polecenie jest równoważne z cat foo >foo. W zależności od catimplementacji może to albo spowodować błąd (wersja GNU narzeka, że ​​„plik wejściowy to plik wyjściowy”), albo może nic nie robić, ponieważ czyta z pliku, fooktóry jest pusty ( >foopo prostu go obciął). W wersji cat, która nie wykrywa tego specjalnego przypadku, jeśli foonie jest pusty, wówczas cat /dev/stdout >>foolub odpowiednik cat foo >>foodołączałby zawartość pliku do siebie na czas nieokreślony.

Po uruchomieniu vim /dev/stdoutnarzeka, ponieważ nie wie, jak edytować terminal (to po prostu nie ma sensu).

Gilles „SO- przestań być zły”
źródło
2

cati tailszukają opcjonalnej treści, po której następuje koniec pliku. /dev/stdoutpozostaje otwarty, więc cati tailszukaj dalej.

Politank-Z
źródło