Pojęcia dotyczące systemu operacyjnego i APUE mówią
W przypadku vfork () proces nadrzędny jest zawieszany, a proces podrzędny wykorzystuje przestrzeń adresową nadrzędnego. Ponieważ vfork () nie używa funkcji kopiowania przy zapisie, jeśli proces potomny zmieni dowolne strony w przestrzeni adresowej rodzica, zmienione strony będą widoczne dla rodzica po wznowieniu. Dlatego vfork () należy używać ostrożnie, aby proces potomny nie modyfikował przestrzeni adresowej rodzica.
vfork () jest przeznaczony do użycia, gdy proces potomny wywołuje exec () lub exit () natychmiast po utworzeniu.
Jak mam zrozumieć ostatnie zdanie?
Kiedy proces potomny utworzony przez vfork()
wywołania exec()
nie exec()
modyfikuje przestrzeni adresowej procesu nadrzędnego, ładując nowy program?
Gdy proces dziecko stworzony przez vfork()
rozmowy exit()
, czy exit()
nie zmodyfikować przestrzeń adresową procesu macierzystego gdy kończące dziecko?
Preferuję Linuksa.
Dzięki.
posix_spawn
. Znacznie trudniej jest napisać poprawny kod używającposix_spawn
starego niż zwykłegofork
, a jeśli spróbujesz, możesz natknąć się na ceglaną ścianę, w której nie ma akcji pliku lub atrybutu, który wykonuje czynności pomiędzyfork
iexec
. I nie ma gwarancji, że ma wydajność podobną do vfork, więc nawet nie rozwiązuje problemu, który ludzie chcą rozwiązać.posix_spawn
może brakować pożądanej funkcjonalności (możesz to rozwiązać za pomocą pośredniczącego programu pomocniczego, napisanego w C lub skrypcie powłoki inline-on-cmdline), każda próba osiągnięcia tego, co chcesz,vfork
wywołuje niebezpieczne niezdefiniowane zachowanie. Specyfikacja parametruvfork
nie zezwala na wywoływanie funkcji losowych w celu ustawienia stanu, w którym dziecko może odziedziczyć wcześniejexecve
, i próby takie mogą uszkodzić stan rodzica.posix_spawn
działa mniej więcej tak samo, jakvfork
w większości warunków. Te, w których występuje różnica, to zwykle przypadki, w którychvfork
jest to bardzo niebezpieczne: gdzie są zainstalowane programy obsługi sygnałów, któreposix_spawn
muszą powstrzymywać się przed uruchomieniem u dziecka przed wykonaniem.Po wywołaniu
vfork()
tworzony jest nowy proces, który pożycza obraz procesu nadrzędnego, z wyjątkiem stosu. Proces potomny otrzymuje własną nową gwiazdkę stosu, jednak nie pozwala nareturn
to funkcja, która go wywołałavfork()
.Podczas gdy dziecko jest uruchomione, proces nadrzędny jest blokowany, ponieważ dziecko pożyczyło przestrzeń adresową rodzica.
Niezależnie od tego, co robisz, wszystko, co tylko uzyskuje dostęp do stosu, modyfikuje tylko prywatny stos dziecka. Jeśli jednak zmodyfikujesz dane globalne, zmodyfikuje to wspólne dane, a zatem wpłynie również na element nadrzędny.
Czynnikami modyfikującymi dane globalne są np .:
wywoływanie malloc () lub free ()
za pomocą stdio
modyfikowanie ustawień sygnału
modyfikowanie zmiennych, które nie są lokalne dla wywoływanej funkcji
vfork()
....
Gdy zadzwonisz
_exit()
(ważne, nigdy nie dzwoniszexit()
), dziecko zostaje zakończone, a kontrola zostaje zwrócona rodzicowi.Jeśli wywołasz dowolną funkcję z
exec*()
rodziny, tworzona jest nowa przestrzeń adresowa z nowym kodem programu, nowymi danymi i częścią stosu nadrzędnego (patrz poniżej). Gdy to jest gotowe, dziecko nie pożycza już przestrzeni adresowej od dziecka, ale używa własnej przestrzeni adresowej.Kontrola jest zwracana rodzicowi, ponieważ jej przestrzeń adresowa nie jest już używana przez inny proces.
Ważne: w systemie Linux nie ma rzeczywistej
vfork()
implementacji. Linux raczej implementuje się wvfork()
oparciu ofork()
koncepcję Copy on Write wprowadzoną przez SunOS-4.0 w 1988 roku. Aby użytkownicy uwierzyli, że ich używająvfork()
, Linux po prostu konfiguruje wspólne dane i zawiesza rodzica, podczas gdy dziecko nie dzwoniło ani żadnej_exit()
zexec*()
funkcji.Linux nie korzysta zatem z faktu, że rzeczywisty
vfork()
nie musi konfigurować opisu przestrzeni adresowej dla dziecka w jądrze. Powoduje to,vfork()
że nie jest szybszy niżfork()
. W systemach, które implementują wartość rzeczywistąvfork()
, jest ona zazwyczaj 3 razy szybszafork()
i wpływa na wydajność używanych powłokvfork()
-ksh93
, najnowszejBourne Shell
icsh
.Powodem, dla którego nigdy nie powinieneś dzwonić
exit()
odvfork()
dziecka ed, jest to, żeexit()
opróżnia stdio w przypadku, gdy dane nie zostały odłączone od czasu przed dzwonieniemvfork()
. Może to powodować dziwne wyniki.BTW:
posix_spawn()
jest zaimplementowanyvfork()
, więcvfork()
nie będzie usuwany z systemu operacyjnego. Wspomniano już, że Linux nie korzystavfork()
zaposix_spawn()
.Dla stosu jest niewiele dokumentacji, oto, co mówi strona podręcznika Solaris:
Implementacja może więc robić, co chce. Implementacja Solaris korzysta z pamięci współużytkowanej dla ramki stosu wywołania funkcji
vfork()
. Żadna implementacja nie zapewnia dostępu do starszych części stosu od rodzica.źródło
posix_spawn()
na Linuksievfork()
. Oboje wdrażają go na szczycie__clone()
.vfork()
tylko dzwonisz,clone()
prawda? Jest dosłownie jednowierszowy w jądrze.vfork
afork
Linuksem, robi coś złego.