Zgodnie z tym i tym , podpowłoka jest uruchamiana za pomocą nawiasu (…)
.
( echo "Hello" )
Zgodnie z tym , to i to , proces jest rozwidlany, gdy polecenie jest uruchamiane za pomocą&
echo "Hello" &
Specyfikacja Posix używa słowa subshell
na tej stronie, ale go nie definiuje, a także na tej samej stronie, nie definiuje „procesu potomnego” .
Oba używają fork()
funkcji jądra , prawda?
Jaka jest dokładna różnica nazywania niektórych rozwidleń „podpowłoką”, a niektórych innych - „procesem potomnym”.
child process
może mieć inne środowisko niżmain
: jak w( LANG=C eval 'echo "$LANG"' )
. Czy ten proces potomny (w nawiasie) jest również podpowłoką (inne środowisko)?( )
jest z definicji podpowłoką z własnym środowiskiem wykonawczym. Chodzi mi o to, że podpowłoka nie musi być implementowana jako proces potomny (jak wskazuje Stéphane w swojej odpowiedzi z przykładem ksh93). Wygląda na to powłoki w tle , a proces potomny nie muszą być obydwa wynikifork()
wezwania; dlatego szukanie różnicy między dwoma rodzajami widelca nie wydaje mi się właściwym punktem widzenia. Właśnie dlatego starałem się lepiej zrozumieć twoje pytanie.Odpowiedzi:
W terminologii POSIX środowisko podpowłoki jest powiązane z pojęciem środowiska wykonawczego powłoki .
Środowisko podpowłoki jest oddzielnym środowiskiem wykonywania powłoki utworzonym jako duplikat środowiska nadrzędnego. To środowisko wykonawcze obejmuje takie rzeczy, jak otwarte pliki, umask, katalog roboczy, zmienne / funkcje / aliasy powłoki ...
Zmiany w tym środowisku podpowłoki nie wpływają na środowisko nadrzędne.
Tradycyjnie w powłoce Bourne'a lub ksh88, na której oparta jest specyfikacja POSIX, zostało to zrobione przez rozwarcie procesu potomnego.
Obszary, w których POSIX wymaga lub pozwala na uruchamianie komend w środowisku podpowłoki, to te, w których tradycyjnie ksh88 rozwidlał proces powłoki potomnej.
Nie zmusza to jednak implementacji do użycia do tego procesu potomnego.
Powłoka może zamiast tego wybrać wdrożenie oddzielnego środowiska wykonawczego w dowolny sposób.
Na przykład, ksh93 robi to poprzez zapisywanie atrybutów nadrzędnego środowiska wykonawczego i przywracanie ich po zakończeniu środowiska podpowłoki w kontekstach, w których można uniknąć rozwidlenia (jako optymalizacja, ponieważ rozwidlanie jest dość kosztowne w większości systemów).
Na przykład w:
POSIX wymaga
cd /foo
działania w osobnym środowisku i wypisywania czegoś takiego:Nie wymaga działania w osobnym procesie. Na przykład, jeśli stdout staje się zepsutą rurą,
pwd
uruchom w środowisku podpowłoki może bardzo dobrze, że SIGPIPE zostanie wysłany do jedynego procesu powłoki.Większość powłok, w tym
bash
, implementuje go, oceniając kod wewnątrz(...)
procesu potomnego (podczas gdy proces macierzysty czeka na jego zakończenie), ale ksh93 zamiast tego uruchomi kod wewnątrz(...)
, wszystko w tym samym procesie:cd
zapisz poprzedni katalog roboczy (zwykle na deskryptorze pliku otwartym za pomocą O_CLOEXEC), zapisz wartość zmiennych OLDPWD, PWD i wszystko, cocd
może zmodyfikować, a następnie wykonajchdir("/bar")
fchdir()
na tym zapisanym fd) i wszystko inne, co podpowłoka mogła zmodyfikować.Istnieją konteksty, w których nie można uniknąć procesu potomnego. ksh93 nie rozwidla się:
var=$(subshell)
(subshell)
Ale robi to
{ subshell; } &
{ subshell; } | other command
Oznacza to, że przypadki muszą przebiegać w osobnych procesach, aby mogły działać równolegle.
Optymalizacje ksh93 idą dalej. Na przykład podczas pobytu w
większość powłok rozwidliłaby proces, gdyby dziecko uruchomiło
pwd
polecenie ze stdout przekierowanym do potoku,pwd
zapisało bieżący katalog roboczy do tego potoku, a proces nadrzędny odczytałby wynik na drugim końcu potoku,ksh93
wirtualizuje to wszystko wymagające widelca ani rury. Widelec i potok byłyby używane tylko dla poleceń niewbudowanych.Zauważ, że istnieją inne konteksty niż podpowłoki, dla których powłoki rozwidlają proces potomny. Na przykład, aby uruchomić polecenie zapisane w osobnym pliku wykonywalnym (który nie jest skryptem przeznaczonym dla tego samego interpretera powłoki), powłoka musiałaby rozwidlić proces, aby uruchomić w nim to polecenie, ponieważ inaczej nie byłby w stanie uruchomić więcej poleceń po powrocie tego polecenia.
W:
To nie jest podpowłoka, polecenie zostanie ocenione w bieżącym środowisku wykonywania powłoki,
n
zmienna bieżącego środowiska wykonywania powłoki zostanie zwiększona, ale powłoka rozwinie proces potomny w celu wykonania tego/bin/echo
polecenia z rozszerzeniem$((n += 1))
as argument .Wiele powłok implementuje optymalizację w taki sposób, że nie rozwidla procesu potomnego, aby uruchomić to polecenie zewnętrzne, jeśli jest to ostatnie polecenie skryptu lub podpowłoki (dla tych podpowłok, które są zaimplementowane jako procesy potomne). (
bash
robi to jednak tylko wtedy, gdy to polecenie jest jedynym poleceniem podpowłoki).Oznacza to, że w przypadku tych powłok, jeśli ostatnie polecenie w podpowłoce jest poleceniem zewnętrznym, podpowłoka nie powoduje odrodzenia dodatkowego procesu. Jeśli porównasz:
z
powstanie taka sama liczba procesów, tylko w drugim przypadku drugie rozwidlenie jest zrobione wcześniej, aby
a=2
było uruchamiane w środowisku podpowłoki.źródło
Subshell
Powłoka potomna jest również nazywana podpowłoką. Podpowłokę można utworzyć z powłoki nadrzędnej i z innej powłoki. Podshell można utworzyć za pomocą:
1. Lista procesów
Lista procesów to grupowanie poleceń ujęte w nawiasy. Przykład:
Spowoduje to wydrukowanie bieżącego katalogu roboczego i liczby spawnowanych powłok. UWAGA Wywołanie podpowłoki jest drogie.
2. Koproces
Odradza podpowłokę w trybie tła i wykonuje polecenie w tej podpowłoce.
Jeśli wpiszesz
jobs
poleceniezobaczysz sen jako proces działający w tle.
Rozwidlenie procesu potomnego
Proces potomny w przetwarzaniu jest procesem utworzonym przez inny proces. Za każdym razem, gdy wykonywane jest polecenie zewnętrzne, tworzony jest proces potomny. To działanie nazywa się rozwidleniem.
Podobnie jak
ps -f
polecenie zewnętrzne (tj. Polecenie zewnętrzne, czasami nazywane poleceniem systemu plików, to program, który istnieje poza powłoką bash). Spowoduje to utworzenie procesu potomnego z nadrzędnym identyfikatorem powłoki bash, z którego jest wykonywany.źródło
Zarówno (podpowłoka, jak i powłoka podrzędna) są osobnym procesem niż powłoka nadrzędna (oba są potomkami powłoki nadrzędnej). Oznacza to, że mają różne PID. I oba zaczynają się od rozwidlenia (kopii) powłoki macierzystej.
Podpowłoka jest kopią powłoki nadrzędnej, w której zmienne, funkcje, flagi i wszystko jest dostępne tak, jak było w powłoce nadrzędnej. Modyfikacje takich wartości nie wpływają na element nadrzędny.
Powłoka podrzędna zaczyna się jako rozwidlenie, ale resetuje się do domyślnych wartości powłoki podanych przez konfiguracje początkowe. Staje się procesem używanym do wykonania jakiegoś kodu (powłoki lub polecenia).
Podkładka może uzyskiwać dostęp do wartości zmiennych:
Powłoka podrzędna nie mogła (nieeksportowane zmienne):
źródło