Podpowłoka zaczyna się jako prawie identyczna kopia oryginalnego procesu powłoki. Pod maską powłoka wywołuje forkwywoł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 $PPIDjest PID rodzica oryginalnej powłoki.
Kilka powłok zmienia kilka zmiennych w podpowłoce. Bash ustawia BASHPIDna PID procesu powłoki, który zmienia się w podpowłoce. Bash, zsh i mksh umożliwiają $RANDOMuzyskanie 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 '' SIGNALtrap 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, 1ponieważ 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 xw drugiej linii nie ma więcej połączenia z xdrugą linią niż w
x=1
perl -le 'print $x'
lub
x=1
python -c 'print x'
1 Wyjątkiem jest ksh93powł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 ERRpułapkę z zagnieżdżonej podpowłoki w przypadku „dwóch podpowłok”, ale nie ERRpułapkę z podpowłoki pośredniej - set -Eopcja powinna propagowaćERRpułapka na wszystkie podpowłoki, ale podpowłoka pośrednia jest zoptymalizowana, więc nie ma jej, aby uruchomić ERRpułapkę.
x=out; (x=in; echo $x))