Яка точна відмінність між «підрозділом» та «дочірнім процесом»?


16

Відповідно до цього та цього , підзаголовок запускається з використанням дужок (…).

( echo "Hello" )

Відповідно до цього , цього і цього , розгортається процес при запуску команди з a&

echo "Hello" &

Специфікація Posix використовує слово subshellна цій сторінці, але не визначає його, а також на цій же сторінці не визначає "дочірній процес" .

Обидва використовують функцію ядра fork(), правда?

Яка точна різниця тоді називати одні вилки "підрозділом", а деякі інші - "дочірнім процесом".


Незрозуміло, чому ви пов'язуєте обгрунтування POSIX : Базові визначення замість самих базових визначень : 3,93 Дочірній процес "Новий процес, створений (за допомогою fork (), posix_spawn () або ...) заданим процесом" ; 3.376 Subshell "Середовище виконання оболонки, відмінне від основного або поточного середовища виконання оболонки" . Отже, не екземпляри одного і того ж речі. Це відмінність, яку ви шукаєте?
фра-сан

@ fra-san A child processможе мати виразніше середовище, ніж main: Як у ( LANG=C eval 'echo "$LANG"' ). Це дочірній процес (всередині дужок) також підгрупа (різне середовище)?
Ісаак

Вираз ( )це за визначенням подоболочкі зі своєю власною середовищем виконання. Моя думка полягає в тому, що допоміжну оболонку не потрібно реалізовувати як дочірній процес (як Стейфан вказує у своїй відповіді на прикладі ksh93). Схоже, що підзарядка та дочірній процес не повинні бути обома результатами fork()дзвінка; таким чином, пошук різниці між двома видами виделки не здається мені правильною точкою зору. Ось чому я намагався краще зрозуміти ваше запитання.
фра-сан

Ах, тепер я бачу, що сторінка tldp, на яку ви посилаєтесь, насправді говорить про те, що нижня частина - це дочірній процес. На мою думку, це визначення є можливим оманливим спрощенням.
фра-сан

Відповіді:


15

У термінології POSIX середовище додаткової оболонки пов'язане з поняттям середовище виконання оболонки .

Навколишнє середовище додаткової оболонки - це окреме середовище виконання оболонки, створене як дублікат батьківського середовища. Це середовище виконання включає такі речі, як відкриті файли, umask, робочий каталог, змінні оболонки / функції / псевдоніми ...

Зміни в цьому середовищі додаткової оболонки не впливають на батьківське середовище.

Традиційно в оболонці Bourne або ksh88, на якій базується специфікація POSIX, це робилося шляхом розпалювання дочірнього процесу.

Області, де POSIX вимагає або дозволяє команді запускатись у середовищі підклітини, це ті області, де ksh88 традиційно розщеплює процес дочірньої оболонки.

Однак це не змушує реалізацію використовувати для цього дочірній процес.

Оболонка може замість цього реалізувати окреме середовище виконання будь-яким способом.

Наприклад, ksh93 робить це, зберігаючи атрибути батьківського середовища виконання та відновлюючи їх після завершення оточення підпрограми в контекстах, де розхитування можна уникнути (як оптимізація, оскільки розгортання є досить дорогим для більшості систем).

Наприклад, у:

cd /foo; pwd
(cd /bar; pwd)
pwd

POSIX вимагає cd /fooзапуску в окремому середовищі і для виведення чогось типу:

/foo
/bar
/foo

Це не вимагає його запуску в окремому процесі. Наприклад, якщо stdout стає зламаною трубою, pwdзапуск у середовищі підпалубки може дуже добре відправити SIGPIPE до єдиного процесу оболонки.

Більшість оболонок в тому числі bashбуде реалізовувати його, оцінюючи код всередині (...)в дочірньому процесі (поки батьківський процес чекає його завершення), але замість ksh93 при запуску коду всередині (...)цього ж процесу:

  • пам’ятайте, що це знаходиться в нижній частині середовища.
  • після цього cdзбережіть попередню робочу директорію (як правило, у дескрипторі файлу, відкритому за допомогою O_CLOEXEC), збережіть значення змінних OLDPWD, PWD та будь-що, що cdможе змінити, а потім зробітьchdir("/bar")
  • після повернення з допоміжної частини поточний робочий каталог відновлюється (з а fchdir()на цьому збереженому fd), а все інше, що можливо, допоміжна зміна.

Існують контексти, коли дочірнього процесу неможливо уникнути. ksh93 не роздвоюється:

  • var=$(subshell)
  • (subshell)

Але робить у

  • { subshell; } &
  • { subshell; } | other command

Тобто випадки, коли речі мають працювати в окремих процесах, щоб вони могли працювати одночасно.

ksh93 оптимізації йдуть далі. Наприклад, перебуваючи в

var=$(pwd)

більшість оболонок розщедрить процес, дозволить дитині запустити pwdкоманду з її stdout, перенаправлену на трубу, pwdзаписати поточну робочу директорію в цю трубу, а батьківський процес зчитує результат на іншому кінці труби, ksh93віртуалізує все, що ні не вимагаючи ані вилки, ані труби. Вилка та труба використовуються лише для невбудованих команд.

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

В:

/bin/echo "$((n += 1))"

Це не додаткова оболонка, команда буде оцінюватися в поточному середовищі виконання оболонки, nзмінна поточного середовища виконання оболонки буде нарощена, але оболонка буде форсувати дочірній процес для виконання цієї /bin/echoкоманди в ньому з розширенням $((n += 1))як аргумент .

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

Це означає, що з цими оболонками, якщо остання команда в допоміжній оболонці - це зовнішня команда, підшалл не викликає породження додаткового процесу. Якщо порівнювати:

a=1; /bin/echo "$a"; a=2; /bin/echo "$a"

з

a=1; /bin/echo "$a"; (a=2; /bin/echo "$a")

буде створено однакову кількість процесів, лише у другому випадку, друга вилка робиться раніше, так що a=2запуск виконується в середовищі нижньої оболонки.


1

Абонемент

Дочірню оболонку ще називають нижньою оболонкою. Subshell може бути створений з батьківської оболонки та з іншої оболонки. Передплату можна створити за допомогою:

1. Список процесів

Список процесів - це групування команд, укладене в дужки. Приклад:

( pwd ; (echo $BASH_SUBSHELL)) 

Це надрукує поточний робочий каталог та кількість породжених оболонок. ПРИМІТКА Здійснення плати за передплату коштує дорого.

2. Копроцес

Він породжує підзарядку у фоновому режимі та виконує команду в межах цієї підпакеті.

coproc sleep 10

Якщо ви введете jobsкоманду

[1]+  Running                 coproc COPROC sleep 10 &

ви побачите сон як фоновий процес, що працює у фоновому режимі.

Розробка процесу для дитини

Дочірній процес в обчислювальній роботі - це процес, створений іншим процесом. Щоразу, коли виконується зовнішня команда, створюється дочірній процес. Ця дія називається розщепленням.

$ps -f
UID        PID  PPID  C STIME TTY          TIME CMD  
umcr7     3647  3638  0 13:54 pts/0    00:00:00 bash
umcr7     3749  3647  0 13:59 pts/0    00:00:00 ps -f

Як ps -fце зовнішня команда (тобто зовнішня команда, яку іноді називають командою файлової системи, це програма, що існує поза оболонкою bash.), Це створить дочірній процес з батьківським ідентифікатором bash shell, з якого він виконується.


0

Обидва (нижня оболонка та дочірня оболонка) є окремим процесом, ніж батьківська оболонка (обидва є дочірніми з батьківської оболонки). Тобто вони мають різні PID. І обидва починаються з вилки (копії) батьківської оболонки.

Піддійна оболонка - це копія батьківської оболонки, в якій змінні, функції, прапори та все доступно так, як було у батьківській оболонці. Зміни таких значень не впливають на батьківські.

Дочірня оболонка починається як виделка, але вона скидається до значень за замовчуванням оболонки, заданих конфігураціями запуску. Це стає процесом, який використовується для виконання деякого коду (або оболонки, або команди).

Підскладок може отримати доступ до змінних значень:

$ x=123; ( echo "$x")
123

Дочірня оболонка не могла (не експортовані змінні):

$ x=234; sh -c 'echo "x=$x"'
x=
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.