Предупреждение: выполнение этой команды в большинстве оболочек приведет к поломке системы, для исправления которой потребуется принудительное отключение
Я понимаю рекурсивную функцию :(){ :|: & };:
и что она делает. Но я не знаю, где находится системный вызов fork. Я не уверен, но я подозреваю в трубе |
.
linux
shell
system-calls
mavillan
источник
источник
Ответы:
В результате конвейера
x | y
создается подоболочка, которая содержит конвейер как часть группы процессов переднего плана. Это продолжает создавать подоболочки (черезfork()
) бесконечно, создавая таким образом вилочную бомбу.Однако на самом деле ответвление не происходит до тех пор, пока код не будет запущен, что является последним вызовом
:
вашего кода.Чтобы разобрать, как работает вилочная бомба:
:()
- определить новую функцию под названием:
{ :|: & }
- определение функции, которое рекурсивно передает вызывающую функцию в другой экземпляр вызывающей функции в фоновом режиме:
- вызвать функцию вилочной бомбыЭто, как правило, не слишком интенсивно использует память, но будет поглощать PID и потреблять циклы процессора.
источник
x | y
, почему есть суб-оболочка создана? Насколько я понимаю, когда bash видит apipe
, он выполняетpipe()
системный вызов, который возвращает дваfds
. Теперь command_left редактируется,exec
и вывод подается в command_right в качестве ввода. Теперь command_right редактируетсяexec
. Итак, почемуBASHPID
каждый раз разные?x
иy
это две отдельные команды, работающие в двух отдельных процессах, так что у вас есть две отдельные вложенные оболочки . Еслиx
выполняется в том же процессе, что и оболочка, это означает, что онx
должен быть встроенным.Последний бит кода,
;:
это функция:(){ ... }
. Это где вилка происходит.Точка с запятой завершает первую команду, а мы запускаем другую, то есть вызываем функцию
:
. Определение этой функции включает в себя вызов самой себя (:
), и результат этого вызова передается в фоновую версию:
. Это поддерживает процесс на неопределенный срок.Каждый раз , когда вы вызываете функцию
:()
вы вызываете функцию Cfork()
. В конечном итоге это приведет к исчерпанию всех идентификаторов процессов (PID) в системе.пример
Вы можете поменяться
|:&
с чем-то другим, чтобы вы могли понять, что происходит.Настройте наблюдателя
В одном окне терминала сделайте это:
Настройте "взрыватель с задержкой" вилка бомба
В другом окне мы запустим слегка модифицированную версию вилочной бомбы. Эта версия попытается задушить себя, чтобы мы могли изучить, что она делает. Наша версия будет спать в течение 61 секунды перед вызовом функции
:()
.Кроме того, мы также отправим фоновый вызов после его вызова. Ctrl+ z, затем введите
bg
.Теперь, если мы запустим
jobs
команду в начальном окне, мы увидим это:Через пару минут:
Проверьте с наблюдателем
Тем временем в другом окне, где мы бежим
watch
:Иерархия процессов
И
ps -auxf
показывает эту иерархию процесса:Время уборки
А
killall bash
остановит вещи прежде, чем они выйдут из-под контроля. Выполнение очистки таким образом может быть немного тяжелым, более мягким способом, который потенциально не разрушит каждуюbash
раковину, было бы сделать следующее:Определите, в каком псевдо-терминале будет работать вилочная бомба
Убить псевдо-терминал
Итак, что происходит?
Хорошо, каждый вызов
bash
иsleep
является вызовом функции Cfork()
изbash
оболочки, из которой была выполнена команда.источник
bash
может работать на отдельных терминалах. Лучше было бы использоватьpkill -t pts/2
.