Согласно этому и этому , подоболочка запускается с использованием круглых скобок (…)
.
( echo "Hello" )
В соответствии с этим , этим и этим процесс разветвляется, когда команда запускается с&
echo "Hello" &
Спецификация Posix использует слово subshell
на этой странице, но не определяет его, а также на той же странице не определяет «дочерний процесс» .
Оба используют fork()
функцию ядра , правильно?
Какая разница в том, чтобы называть некоторые вилки «вложенной оболочкой», а некоторые другие - «дочерними процессами».
child process
может иметь отличную среду, чемmain
: Как в( LANG=C eval 'echo "$LANG"' )
. Является ли этот дочерний процесс (внутри круглых скобок) также подоболочкой (в другой среде)?( )
это по определению Подоболочка со своей собственной средой исполнения. Я хочу сказать, что подоболочка не должна быть реализована как дочерний процесс (как указывает Стефан в своем ответе на примере ksh93). Похоже, подоболочка и дочерний процесс не должны быть оба результатаfork()
вызова; таким образом, поиск различий между двумя типами вилок не кажется мне правильной точкой зрения. Вот почему я пытался лучше понять ваш вопрос.Ответы:
В терминологии POSIX среда подоболочки связана с понятием среды выполнения Shell .
Среда subshell - это отдельная среда выполнения оболочки, созданная как дубликат родительской среды. Эта среда выполнения включает в себя такие вещи, как открытые файлы, umask, рабочий каталог, переменные оболочки / functions / aliases ...
Изменения в этой среде оболочки не влияют на родительскую среду.
Традиционно в оболочке Bourne или ksh88, на которой основана спецификация POSIX, это было сделано путем разветвления дочернего процесса.
Области, где POSIX требует или разрешает запуск команды в среде подоболочек, - это области, где традиционно ksh88 разветвлял дочерний процесс оболочки.
Однако это не заставляет реализации использовать дочерний процесс для этого.
Вместо этого оболочка может реализовать эту отдельную среду выполнения любым удобным для них способом.
Например, ksh93 делает это, сохраняя атрибуты родительской среды выполнения и восстанавливая их после завершения среды subshell в тех случаях, когда можно избежать разветвления (поскольку оптимизация, поскольку разветвление довольно дорого в большинстве систем).
Например, в:
POSIX требует,
cd /foo
чтобы он работал в отдельной среде и выводил что-то вроде:Он не требует запуска в отдельном процессе. Например, если stdout становится прерванным каналом,
pwd
запуск в среде subshell вполне может иметь отправку SIGPIPE в один-единственный процесс оболочки.Большинство оболочек, в том числе
bash
, реализуют его, оценивая код внутри(...)
дочернего процесса (пока родительский процесс ожидает его завершения), но вместо этого ksh93 выполнит код внутри(...)
, все в одном процессе:cd
, сохранить предыдущий рабочий каталог ( как правило дескриптор файла , открытый O_CLOEXEC), за исключением стоимости OLDPWD, PWD переменных и все , чтоcd
может изменить , а затем сделатьchdir("/bar")
fchdir()
сохраненным fd) и всем остальным, что subshell мог изменить.Существуют контексты, в которых нельзя избежать дочернего процесса. ksh93 не разветвляется:
var=$(subshell)
(subshell)
Но делает в
{ subshell; } &
{ subshell; } | other command
То есть случаи, когда вещи должны запускаться в отдельных процессах, чтобы они могли работать одновременно.
Оптимизация ksh93 идет дальше этого. Например, в то время как в
большинство оболочек будет обрабатывать процесс, дочерний процесс запускает
pwd
команду с перенаправленным stdout в канал,pwd
записывает текущий рабочий каталог в этот канал, а родительский процесс считывает результат на другом конце канала,ksh93
виртуализирует все это ни одним из них. требуя вилки или трубы. Вилка и труба будут использоваться только для не встроенных команд.Обратите внимание, что существуют контексты, отличающиеся от подоболочек, для которых оболочки разветвляют дочерний процесс. Например, чтобы запустить команду, которая хранится в отдельном исполняемом файле (и это не сценарий, предназначенный для того же интерпретатора оболочки), оболочка должна была бы разветвить процесс, чтобы запустить в нем эту команду, иначе это было бы не так. возможность выполнить больше команд после того, как эта команда вернется.
В:
Это не подоболочка, команда будет оцениваться в текущей среде выполнения оболочки,
n
переменная текущей среды выполнения оболочки будет увеличиваться, но оболочка будет разветвлять дочерний процесс для выполнения этой/bin/echo
команды с расширением$((n += 1))
аргумента as. ,Многие оболочки реализуют оптимизацию в том смысле, что они не разветвляют дочерний процесс для запуска этой внешней команды, если это последняя команда скрипта или подоболочки (для тех подоболочек, которые реализованы как дочерние процессы). (
bash
однако это происходит только в том случае, если эта команда является единственной командой подоболочки).Это означает, что с этими оболочками, если последняя команда в подоболочке является внешней командой, подоболочка не приводит к созданию дополнительного процесса. Если вы сравните:
с
будет создано такое же количество процессов, только во втором случае второй ветвь выполняется раньше, так что
a=2
он запускается в среде подоболочек.источник
подоболочка
Дочерняя оболочка также называется subshell. Subshell может быть создан из родительской оболочки и из другой оболочки. Subshell может быть создан с помощью:
1. Список процессов
Список процессов - это группировка команд, заключенная в круглые скобки. Пример:
Это напечатает текущий рабочий каталог и номер порожденной оболочки. ПРИМЕЧАНИЕ. Вызвать подоболочку дорого.
2. Копроцесс
Он порождает подоболочку в фоновом режиме и выполняет команду внутри этой подоболочки.
Если вы введете
jobs
командувы увидите сон как фоновый процесс, работающий в фоновом режиме.
Форкинг дочернего процесса
Дочерний процесс в вычислениях - это процесс, созданный другим процессом. Всякий раз, когда выполняется внешняя команда, создается дочерний процесс. Это действие называется разветвлением.
Как
ps -f
и внешняя команда (т. Е. Внешняя команда, иногда называемая командой файловой системы, представляет собой программу, которая существует вне оболочки bash.) Она создаст дочерний процесс с родительским идентификатором оболочки bash, из которой она выполняется.источник
Оба (subshell и дочерняя оболочка) являются отдельным процессом, нежели родительская оболочка (оба являются дочерними элементами родительской оболочки). То есть у них разные PID. И оба начинаются с форка (копии) родительской оболочки.
Подоболочка - это копия родительской оболочки, в которой переменные, функции, флаги и все доступно, как это было в родительской оболочке. Модификации таких значений не влияют на родителя.
Дочерняя оболочка запускается как ветвь, но возвращается к значениям оболочки по умолчанию, заданным в начальных настройках. Это становится процессом, используемым для выполнения некоторого кода (или оболочки, или команды).
Подоболочка может получить доступ к значениям переменных:
Дочерняя оболочка не может (не экспортируемые переменные):
источник