Betrachten Sie Folgendes (mit sh
Sein /bin/dash
):
$ strace -e trace=process sh -c 'grep "^Pid:" /proc/self/status /proc/$$/status'
execve("/bin/sh", ["sh", "-c", "grep \"^Pid:\" /proc/self/status /"...], [/* 47 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7fcc8b661540) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fcc8b661810) = 24865
wait4(-1, /proc/self/status:Pid: 24865
/proc/24864/status:Pid: 24864
[{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 24865
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=24865, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
exit_group(0) = ?
+++ exited with 0 +++
Es gibt nichts Ungewöhnliches, grep
ersetzt einen gegabelten Prozess (hier über clone()
) durch den Haupt-Shell-Prozess. So weit, ist es gut.
Jetzt mit Bash 4.4:
$ strace -e trace=process bash -c 'grep "^Pid:" /proc/self/status /proc/$$/status'
execve("/bin/bash", ["bash", "-c", "grep \"^Pid:\" /proc/self/status /"...], [/* 47 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f8416b88740) = 0
execve("/bin/grep", ["grep", "^Pid:", "/proc/self/status", "/proc/25798/status"], [/* 47 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f8113358b80) = 0
/proc/self/status:Pid: 25798
/proc/25798/status:Pid: 25798
exit_group(0) = ?
+++ exited with 0 +++
Hier ist offensichtlich, dass grep
PID des Shell-Prozesses und kein offensichtlicher fork()
oder clone()
Aufruf vorausgesetzt wird . Die Frage ist also, wie man bash
eine solche Akrobatik ohne einen der Aufrufe erreicht.
Beachten Sie jedoch, dass clone()
syscalls angezeigt wird, wenn der Befehl eine Shell-Umleitung enthält, zdf > /dev/null
CMD_NO_FORK
execve
da er sleep
eingebaut ist, aber Homers Antwort beantwortet ihn angemessen, aber auch hier nur eine kurze Zusammenfassung. Ich hätte wohl erwähnen sollen, dass ich nach exakten Mechanismen auf Quellcode-Ebene gesucht habe. Würden Sie sagen, dass meine Antwort geeignet ist, Homers in diesem Beitrag zu unterstützen? Es macht mir nichts aus, wenn dieser Beitrag geschlossen wird. Ich habe die Antwort so oder so bekommen
grep
.bash
ist möglicherweise intelligent genug, um nicht zu verzweigen, wenn nur ein einziger externer Befehl ausgeführt wird.