Підскладок починається як майже ідентична копія оригінального процесу оболонки. Під кришкою оболонка викликає fork
системний виклик 1 , який створює новий процес, код і пам'ять якого - копії 2 . Коли створено нижню частину корпусу, різниці між нею та її батьком є дуже мало. Зокрема, вони мають однакові змінні. Навіть $$
спеціальна змінна зберігає однакове значення в підрозділах: це вихідний ідентифікатор процесу оболонки. Аналогічно $PPID
є ідентифікатор PID вихідної оболонки.
Кілька оболонок змінюють декілька змінних в нижній частині корпусу. Bash встановлює BASHPID
PID процесу оболонки, який змінюється в підрозділах. Bash, zsh і mksh організують $RANDOM
отримання різних значень у батьківській та в нижній частині. Але крім вбудованих спеціальних випадків на кшталт цього, всі змінні мають те саме значення в підшкільній оболонці, як і в початковій оболонці, той же статус експорту, той же статус лише для читання тощо. інші настройки також успадковуються.
Подоболочка творець (…)
має ті ж дескриптори файлів , як його творець. Деякі інші засоби створення підшаровок змінюють деякі дескриптори файлів перед виконанням коду користувача; наприклад, ліва частина труби працює в нижній частині корпусу 3 зі стандартним виходом, з'єднаним з трубою. Підсерія також починається з того ж поточного каталогу, тієї ж маски сигналу тощо. Одним з небагатьох винятків є те, що підрозділи не успадковують власні пастки: ігноровані сигнали ( ) залишаються ігнорованими в підрозділі, але інші пастки ( SIGNAL ) скидаються. до дії за замовчуванням 4 .trap '' SIGNAL
trap CODE
Таким чином, додаткова оболонка відрізняється від виконання сценарію. Сценарій - це окрема програма. Ця окрема програма може бути збігом випадкових випадків також і скриптом, який виконується тим же інтерпретатором, що і батьківський, але цей збіг не надає окремій програмі особливої видимості щодо внутрішніх даних батьків. Неекспортні змінні є внутрішніми даними, тому коли інтерпретатор дочірнього сценарію оболонки виконується , він не бачить цих змінних. Експортовані змінні, тобто змінні середовища, передаються виконуваним програмам.
Таким чином:
x=1
(echo $x)
друкує, 1
оскільки нижня оболонка - це реплікація оболонки, яка породила її.
x=1
sh -c 'echo $x'
трапляється запускати оболонку як дочірній процес оболонки, але x
другий рядок не має більшого зв'язку з x
другою лінією, ніж у
x=1
perl -le 'print $x'
або
x=1
python -c 'print x'
1 Виняток становить ksh93
оболонка, де оптимізація розгортання та більша частина її побічних ефектів імітуються.
2 Семантично це копії. З точки зору впровадження, багато обміну відбувається.
3 Для правого боку це залежить від оболонки.
4 Якщо ви перевірите це, зауважте, що такі речі$(trap)
можуть повідомляти про пастки оригінальної оболонки. Зауважте також, що у багатьох оболонках є помилки у кутових корпусах із пастками. Наприклад, ninjalj зазначає, що, починаючи з bash 4.3, bash -x -c 'trap "echo ERR at \$BASH_SUBSHELL \$BASHPID" ERR; set -E; false; echo one subshell; (false); echo two subshells; ( (false) )'
запускає ERR
пастку з вкладеної нижньої оболонки у випадку "дві підзахисні частини", але не ERR
пастка з проміжної нижньої оболонки - set -E
варіант повинен розповсюджуватиERR
пастка до всіх підпакетів, але проміжна піддошка оптимізована і тому не існує для запуску її ERR
пастки.
x=out; (x=in; echo $x)
)