fork
, если все идет хорошо, возвращается дважды. Один возврат происходит в родительском процессе (который имеет исходный ID процесса), а второй - в новом дочернем процессе (с другим ID процесса, но имеющим много общего с родительским процессом). В этот момент дочерний процесс может exec(3)
что-то сделать, что приведет к загрузке "нового" двоичного файла в этот процесс, хотя дочерний процесс не обязательно должен это делать, он может выполнять другой код, уже загруженный через родительский процесс (функции zsh, например). Следовательно, fork
может привести или не привести к "совершенно новому" процессу, если под "совершенно новым" понимать что-то загруженное через exec(3)
системный вызов.
Угадать заранее, какие команды вызывают бесконечный регресс, непросто; кроме случая с вилкой-вызовом-вилкой (он же "вилочная бомба"), другой легкий вариант - это наивная функциональная обертка вокруг некоторой команды
function ssh() {
ssh -o UseRoaming=no "$@"
}
которую вместо этого, вероятно, следует записать как
function ssh() {
=ssh -o UseRoaming=no "$@"
}
или command ssh ...
, чтобы избежать бесконечных вызовов функции ssh
, вызывающей функцию ssh
, вызывающую функцию .... Это никак не связано с fork
, так как вызовы функций являются внутренними для процесса ZSH, но будут весело уходить в бесконечность до тех пор, пока этот единственный процесс ZSH не наткнется на какой-то предел.
strace
, как всегда, удобен для выявления точных системных вызовов для любой команды (в частности, здесь fork
и, возможно, некоторые exec
вызовы); оболочки могут быть отлажены с помощью -x
или аналогичных, которые показывают, что оболочка делает внутри (например, вызовы функций). Для дополнительного чтения у Стивенса в "Advanced Programming in the Unix Environment" есть несколько глав, связанных с созданием и обработкой новых процессов.
Вы можете сделать это с помощью GNU cpio :
$ find . | cpio -o -H newc > /tmp/file
40 blocks
$ file /tmp/file
/tmp/file: ASCII cpio archive (SVR4 with no CRC)