Podpowłoka zaczyna się jako prawie identyczna kopia oryginalnego procesu powłoki. Pod maską powłoka wywołuje fork
wywołanie systemowe 1 , które tworzy nowy proces, którego kod i pamięć są kopiami 2 . Po utworzeniu podpowłoki istnieje bardzo niewiele różnic między nią a jej elementem nadrzędnym. W szczególności mają te same zmienne. Nawet $$
specjalna zmienna zachowuje tę samą wartość w podpowłokach: jest to identyfikator procesu oryginalnej powłoki. Podobnie $PPID
jest PID rodzica oryginalnej powłoki.
Kilka powłok zmienia kilka zmiennych w podpowłoce. Bash ustawia BASHPID
na PID procesu powłoki, który zmienia się w podpowłoce. Bash, zsh i mksh umożliwiają $RANDOM
uzyskanie różnych wartości w rodzicu i podpowłoce. Ale oprócz wbudowanych specjalnych przypadków takich jak te, wszystkie zmienne mają taką samą wartość w podpowłoce jak w oryginalnej powłoce, ten sam status eksportu, ten sam status tylko do odczytu itp. Wszystkie definicje funkcji, definicje aliasów, opcje powłoki i inne ustawienia są również dziedziczone.
Podkładka utworzona przez (…)
ma takie same deskryptory plików jak jej twórca. Niektóre inne sposoby tworzenia podpowłoki modyfikują niektóre deskryptory plików przed wykonaniem kodu użytkownika; na przykład lewa strona rury biegnie w podpowłoce 3 ze standardowym wyjściem podłączonym do rury. Podpowłoka również zaczyna się od tego samego bieżącego katalogu, tej samej maski sygnału itp. Jednym z kilku wyjątków jest to, że podpowłoki nie dziedziczą pułapek niestandardowych: ignorowane sygnały ( ) pozostają ignorowane w podpowłoce, ale inne pułapki ( SYGNAŁ ) są resetowane do domyślnej akcji 4 .trap '' SIGNAL
trap CODE
Zatem podpowłoka różni się od wykonywania skryptu. Skrypt jest osobnym programem. Ten osobny program może być przypadkowo również skryptem, który jest wykonywany przez tego samego interpretera, co rodzic, ale ten przypadek nie zapewnia osobnemu programowi żadnej szczególnej widoczności wewnętrznych danych rodzica. Nieeksportowane zmienne są danymi wewnętrznymi, więc gdy wykonywany jest interpreter skryptu powłoki potomnej , nie widzi tych zmiennych. Eksportowane zmienne, tj. Zmienne środowiskowe, są przekazywane do wykonywanych programów.
A zatem:
x=1
(echo $x)
wypisuje, 1
ponieważ podpowłoka jest replikacją powłoki, która ją zrodziła.
x=1
sh -c 'echo $x'
zdarza się, że uruchamia powłokę jako proces potomny powłoki, ale x
w drugiej linii nie ma więcej połączenia z x
drugą linią niż w
x=1
perl -le 'print $x'
lub
x=1
python -c 'print x'
1 Wyjątkiem jest ksh93
powłoka, w której rozwidlenie jest zoptymalizowane i emulowana jest większość jego skutków ubocznych.
2 Semantycznie są kopiami. Z punktu widzenia implementacji dzieje się dużo udostępniania.
3 Po prawej stronie zależy to od skorupy.
4 Jeśli to przetestujesz, zauważ, że takie rzeczy$(trap)
mogą zgłaszać pułapki oryginalnej powłoki. Zauważ też, że wiele pocisków ma błędy w narożnych skrzyniach z pułapkami. Na przykład ninjalj zauważa, że od wersji 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) )'
uruchamia ERR
pułapkę z zagnieżdżonej podpowłoki w przypadku „dwóch podpowłok”, ale nie ERR
pułapkę z podpowłoki pośredniej - set -E
opcja powinna propagowaćERR
pułapka na wszystkie podpowłoki, ale podpowłoka pośrednia jest zoptymalizowana, więc nie ma jej, aby uruchomić ERR
pułapkę.
x=out; (x=in; echo $x)
)