Ich betrachte die Strace-Ausgabe eines laufenden Bash-Prozesses, der mit einem Terminal verbunden ist, zu Bildungszwecken.
Mein Bash-Prozess hat PID 2883.
Ich tippe
[OP@localhost ~]$ strace -e trace=openat,read,write,fork,vfork,clone,execve -p 2883 2> bash.strace
In ein Terminal. Ich gehe dann in meinen Bash-Prozess und habe die folgende Interaktion:
[OP@localhost ~]$ ls
Wenn ich mir die Ausgabe anschaue, sehe ich
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
...
Ich bin in den letzten beiden Zeilen verwirrt. Es scheint, dass bash versucht, zwei Shell-Eingabeaufforderungen zu schreiben? Was ist denn hier los?
cat
, gibt es zwei Unterschiede: Es liest die Eingabe Zeile für Zeile, und während es seine Eingabe an stdout zurücksendet, sehe ich die Eingabe zweimal (einmal, wenn ich tippe, und einmal, wenn cat sie wiedergibt).^A
(Strg-A) oder die verschiedenen Sonderzeichen gedrückt werden. Außerdem wird das Echo des Terminals ausgeschaltet, sodass entschieden werden kann, was für jedes bestimmte Eingabezeichen ausgegeben werden soll (TAB gibt normalerweise kein TAB aus.)cat
. Wenn Sie esdash
tun , versuchen Sie es auszuführen , was keine Befehlszeilenbehandlung übernimmt.read()
um jeweils nur ein Byte zu lesen, ist, dass es nicht über eine neue Zeile hinaus lesen kann. Der Zeilenumbruch kann dazu führen, dass ein externes Programm ausgeführt wird, das möglicherweise auch von derselben Eingabe liest. (Und dieses Programm sollte in der Lage sein, alle Zeichen nach dem Zeilenumbruch zu lesen.) Wenn es sich nicht darum kümmern müsste, könnte esread()
mit einem größeren Limit aufrufen , und wenn sich das Terminal im Raw-Modus befindet, würde es normalerweise immer noch die Eingabe erhalten jeweils ein Zeichen. (Es würde davonread()
mit größerem Puffer möglicherweise immer noch beide Zeilen zurück der gleiche Anruf. Ich glaube nicht, dass es eine Garantie gibt,read()
die im gekochten Modus immer nur eine Zeile zurückgibt.