Чому в нижній частині корпусу відображається змінна?


18

Книга Learning Bash згадує про те, що субшалл успадкує лише змінні середовища та дескриптори файлів тощо, і що він не буде успадковувати змінні, які не експортуються:

$ var=15
$ (echo $var)
15
$ ./file # this file include the same command echo $var

$

Як я знаю, оболонка створить дві підзаголовки для ()і для ./file, але чому у ()випадку підпакет ідентифікує varзмінну, хоча вона не експортується, а у ./fileвипадку, якщо вона її не ідентифікувала?

# Strace for () 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25617
# Strace for ./file
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25631

Я намагався використати, straceщоб зрозуміти, як це відбувається, і на диво я виявив, що bash використовуватиме однакові аргументи для виклику системи клонування, тому це означає, що обидва роздвоєні процеси в ()і ./fileповинні мати однаковий адресний простір батьків, тому чому у ()випадку, коли змінна видима для підрозділу і те ж саме не відбувається для ./fileвипадку, хоча ті ж аргументи базуються на виклику системи клонування?


vinc17 говорять правдиво, навіть якщо ви отримуєте pstree, коли у вас є передплата, ви вірите в це.
PersianGulf

Відповіді:


15

Книга навчальних башів неправильна. Підзаголовки успадковують усі змінні. Рівно $$(PID оригінальної оболонки) зберігається. Причина полягає в тому, що для нижньої оболонки оболонка просто розщеплюється та не виконує нову оболонку (навпаки, коли ви вводите ./file, виконується нова команда, наприклад, нова оболонка; у виведенні страйку дивіться на execveта ін.) . Тож, в основному, це лише копія (з деякими задокументованими відмінностями).

Примітка: це не характерно для bash; це справедливо для будь-якої оболонки.


Добре, але я спробував зараз промацувати оболонку, і я намагався виконати ./file, але я не можу знайти жодного виклику для exec, і тому адресний простір повинен бути однаковим для обох процесів, так як це можна пояснити?
користувач3718463

@ user3718463 Чи використовували ви -fваріант straceвідстеження дітей? Це необхідно, щоб знайти виконавця.
vinc17

так, я розумію, дякую багато, мені не вистачало опції -f, і тому я не можу знайти виклик exec sys
user3718463

16

Або ви, або книга плутаєте підзаголовки з підпроцесом, який є оболонкою.

Деякі конструкції оболонки призводять до того, що оболонка примушує дочірній процес. Під Linux fork- це окремий випадок більш загального cloneсистемного виклику, який ви спостерігали в straceжурналі. Дитина виконує частину сценарію оболонки. Дочірній процес називається допоміжною . Найбільш прямим такою конструкцією є command1 &: command1запускається в підпакеті, а наступні команди виконуються в батьківській оболонці. Інші конструкції, які створюють підзарядку, включають підстановку команд $(command2)і канали command3 | command4( command3працює в нижній command4оболонці , працює в нижній частині корпусу в більшості оболонок, але не в ksh або zsh).

Піддіаграма - це копія батьківського процесу, тому вона має не тільки однакові змінні середовища, але й усі однакові внутрішні визначення: змінні (включаючи $$ідентифікатор процесу вихідного процесу оболонки), функції, псевдоніми, параметри тощо. Перед виконанням коду в нижній графі, bash встановлює змінну BASHPIDдо ідентифікатора процесу дочірнього процесу.

Під час запуску ./fileце виконує зовнішню команду. По-перше, шкаралупа виливає дочірній процес; то цей дочірній процес виконує (за допомогою execveсистемного виклику) виконуваний файл ./file. Дочірній процес успадковує атрибути процесів своїх батьків: оточення, поточний каталог тощо. Внутрішні аспекти програми втрачаються у execveвиклику: неекспортовані змінні, функції тощо - це базові поняття, про які ядро ​​не знає, і вони втрачаються, коли bash виконує іншу програму. Навіть якщо ця інша програма буває скриптом bash, вона виконується новим екземпляром bash, який не знає і не піклується про те, щоб його батьківський процес також був екземпляром bash. Таким чином, змінна оболонки (неекспортна змінна) не виживає execve.


Ця відповідь прояснила для мене досить багато речей. Єдине, чого я не розумію, це це речення у другому абзаці: "Дитина виконує частину сценарію оболонки". Про який сценарій оболонки йдеться?
flow2k

@ flow2k Сценарій (тобто програма), яку інтерпретує оболонка.
Жил "ТАК - перестань бути злим"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.