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 ^C
ja 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”?
Odpowiedzi:
Nie dostajesz „zawieszania się” od
cat(1)
itail(1)
, one po prostu blokują się podczas odczytu.cat(1)
czeka na dane wejściowe i drukuje je, gdy tylko zobaczy pełny wiersz:Tutaj wpisałem
foo
Enterbar
EnterCTRL- D.tail(1)
czeka na dane wejściowe i drukuje je tylko wtedy, gdy może wykryćEOF
:Tutaj Wpisałem ponownie
foo
Enterbar
EnterCTRL- D.Vim jest jedynym, który daje ci błąd. Robi to, ponieważ działa
stat(2)
przeciwko/dev/stdout
i stwierdza, że nie maS_IFREG
ustawionego bitu./dev/stdout
to 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:Na OpenBSD:
Na FreeBSD:
źródło
(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/stdout
może być jedną z kilku rzeczy w zależności od wariantu unix:W każdym razie otwieranie
/dev/stdout
i 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/stdout
działa dokładnie tak samo jakcat /dev/stdin
lubcat /dev/stderr
, ponieważ te trzy deskryptory plików są podłączone do tego samego pliku: nakazujecat
odczyt z terminala. Właśnie tocat
bez argumentu.Jeśli uruchomiłeś
cat /dev/stdout >foo
, to/dev/stdout
odniósłby się do plikufoo
- to polecenie jest równoważne zcat foo >foo
. W zależności odcat
implementacji 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,foo
który jest pusty (>foo
po prostu go obciął). W wersjicat
, która nie wykrywa tego specjalnego przypadku, jeślifoo
nie jest pusty, wówczascat /dev/stdout >>foo
lub odpowiednikcat foo >>foo
dołączałby zawartość pliku do siebie na czas nieokreślony.Po uruchomieniu
vim /dev/stdout
narzeka, ponieważ nie wie, jak edytować terminal (to po prostu nie ma sensu).źródło
cat
itail
szukają opcjonalnej treści, po której następuje koniec pliku./dev/stdout
pozostaje otwarty, więccat
itail
szukaj dalej.źródło