Patrzę na dane wyjściowe strace uruchomionego procesu bash podłączonego do terminala, do celów edukacyjnych.
Mój proces bash ma PID 2883.
Piszę
[OP@localhost ~]$ strace -e trace=openat,read,write,fork,vfork,clone,execve -p 2883 2> bash.strace
Do terminala. Następnie przechodzę do procesu bash i mam następującą interakcję:
[OP@localhost ~]$ ls
Widzę, patrząc na wynik
strace: Process 2883 attached
read(0, "l", 1) = 1
write(2, "l", 1) = 1
read(0, "s", 1) = 1
write(2, "s", 1) = 1
read(0, "\r", 1) = 1
write(2, "\n", 1) = 1
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fec6b1d8e50) = 3917
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=3917, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
write(1, "\33]0;OP@localhost:~\7", 23) = 23
write(2, "[OP@localhost ~]$ ", 22) = 22
...
Jestem zmieszany na dwóch ostatnich liniach. Wygląda na to, że bash próbuje napisać dwa monity powłoki? Co tu się dzieje?
cat
, istnieją dwie różnice: odczytuje dane wejściowe linia po linii i chociaż echo wprowadza dane z powrotem na standardowe wyjście, widzę dane wejściowe dwa razy (raz, gdy piszę, a raz, gdy kot je echa).^A
naciśnięciu np. Znaku TAB lub (Ctrl-A) lub różnych znaków specjalnych. Ponadto wyłącza echo terminala, aby mógł zdecydować, co wyprowadzić dla każdego konkretnego znaku wejściowego (ponownie, TAB zwykle nie wypisuje TAB.)cat
Nic z tego nie robi. Jeśli tak, spróbuj uruchomićdash
, który nie obsługuje żadnej linii poleceń.read()
tylko do odczytu jednego bajtu na raz, jest to, że nie może on odczytać nowego wiersza. Nowy wiersz może powodować uruchomienie zewnętrznego programu, który może również czytać z tego samego wejścia. (I ten program powinien być w stanie odczytać dowolne znaki po nowej linii.) Gdyby nie musiał się tym przejmować, mógłby wywoływaćread()
z większym limitem, a przy terminalu w trybie surowym nadal zwykle pobierałby dane wejściowe jedna postać na raz. (To zależy od tego, jak szybko pojawią się znaki wejściowe i jak zaplanowano proces.)read()
większy bufor może nadal zwrócić obie linie w to samo połączenie. Nie sądzę, aby istniała gwarancja,read()
która zawsze zwróciłaby tylko jedną linię w trybie gotowania.