W jaki sposób kopiowanie przy zapisie w fork () obsługuje wiele fork?


23

Według Wikipedii (co może być błędne)

Po wydaniu wywołania systemowego fork () tworzona jest kopia wszystkich stron odpowiadających procesowi nadrzędnemu, ładowana przez system operacyjny do osobnego miejsca w pamięci dla procesu potomnego. Ale w niektórych przypadkach nie jest to konieczne. Rozważ przypadek, gdy dziecko wykonuje execwywołanie systemowe ("używane do wykonania dowolnego pliku wykonywalnego z programu C) lub kończy pracę wkrótce po fork(). Gdy dziecko jest potrzebne tylko do wykonania polecenia dla procesu nadrzędnego, nie ma potrzeby kopiowania stron procesu nadrzędnego, ponieważ execzastępuje przestrzeń adresową procesu, który ją wywołał, poleceniem do wykonania.

W takich przypadkach stosowana jest technika zwana kopiowaniem przy zapisie (COW). Dzięki tej technice, gdy występuje rozwidlenie, strony procesu nadrzędnego nie są kopiowane do procesu potomnego. Zamiast tego strony są współużytkowane przez proces podrzędny i nadrzędny. Ilekroć proces (rodzic lub dziecko) modyfikuje stronę, tworzona jest osobna kopia samej strony dla tego procesu (rodzic lub dziecko), który dokonał modyfikacji. Ten proces będzie wykorzystywał nowo skopiowaną stronę zamiast udostępnionej we wszystkich przyszłych odniesieniach. Drugi proces (ten, który nie zmodyfikował udostępnionej strony) nadal korzysta z oryginalnej kopii strony (która nie jest już udostępniana). Ta technika nazywa się kopiowaniem przy zapisie, ponieważ strona jest kopiowana, gdy jakiś proces do niej zapisuje.

Wygląda na to, że gdy którykolwiek z procesów próbuje zapisać na stronie, nowa kopia strony zostaje przydzielona i przypisana do procesu, który wygenerował błąd strony. Oryginalna strona zostaje następnie oznaczona do zapisu.

Moje pytanie brzmi: co się stanie, jeśli fork()wywołanie zostanie wywołane wiele razy, zanim którykolwiek z procesów spróbuje napisać na udostępnionej stronie?


Wikipedia ma rację w tym przypadku, tylko na wyższym poziomie.
Didi Kohen,

1
Tak, kopiowanie przy zapisie jest leniwym kopiowaniem, proces potomny kopiuje stronę przy próbie jej napisania. Zasadniczo po rozwidleniu pamięć niemal dziecka jest dzielona z rodzicem. Jednak przed wykonaniem któregokolwiek z procesów każdy proces potomny nadal ma pewną pamięć prywatną, zmodyfikowaną z przydziału macierzystego lub nowego przydziału. Oznacza to, że nawet bez żadnego działania rozwidlony proces potomny ma pewną pamięć prywatną. Możemy to zweryfikować za pomocą pmap -XX PIDlub cat /proc/PID/smap.
gdzie23

Jeśli chodzi o - „Oryginalna strona zostanie później oznaczona do zapisu.”, Kto będzie jej właścicielem? Oto inny proces, który nie próbował tego napisać?
Adil

To jest urocze. Nauczmy tego w przedszkolach
ed22

Odpowiedzi:


18

Nic szczególnego się nie dzieje. Wszystkie procesy współużytkują ten sam zestaw stron i każdy otrzymuje swoją prywatną kopię, gdy chce zmodyfikować stronę.


Dobrze. Chodzi o to, że jest to proces potomny, który jest specjalny, który ma za zadanie kopiowanie, jeśli próbuje pisać na udostępnionej stronie. Ani rodzic, ani inne dzieci nie muszą wiedzieć o zmianie, jeśli zostanie ona wykonana poprawnie.
Charles Stewart,

9
Proces potomny nie jest tak wyjątkowy. Zarówno procesy potomne, jak i macierzyste mają ten sam zestaw stron tylko do odczytu po rozwidleniu. Jeśli chodzi o te strony, obsługa stron jest symetryczna.
jlliagre,

3

Zachowanie fork () zależy od tego, czy system * nix ma MMU, czy nie. W systemie innym niż MMU (takim jak wczesne PDP-11) wywołanie systemowe fork () skopiowało całą pamięć rodzica dla każdego dziecka. W systemie * nix opartym na MMU jądro zaznacza wszystkie strony bez stosu jako R / O i dzieli je między rodzicem a dzieckiem. Następnie, gdy którykolwiek proces zapisuje na dowolnej stronie, MMU przechwytuje próbę, jądro przydziela stronę do zapisu i aktualizuje tabele stron MMU, aby wskazywały na stronę, którą można teraz zapisać. To zachowanie kopiowania przy zapisie przyspiesza, ponieważ początkowo tylko prywatny stos musi zostać przydzielony i sklonowany dla każdego procesu potomnego.

Jeśli wykonasz jakiś kod nadrzędny między każdym wywołaniem fork (), wówczas wynikowe procesy podrzędne będą się różnić stronami zmienionymi przez nadrzędny. Z drugiej strony, jeśli rodzic po prostu wyda wiele wywołań fork (), np. W pętli, wówczas procesy potomne będą prawie identyczne. Jeśli używana jest zmienna pętli lokalnej, będzie ona inna w stosie każdego dziecka.


0

Gdy system przygotowuje rozwidlenie, zwykle (może to zależeć od implementacji) oznacza również strony jako tylko do odczytu i oznacza proces nadrzędny jako wzorzec tych stron.
Podczas próby zapisu na tych stronach występuje błąd strony i system operacyjny przejmuje kontrolę, kopiując całą listę stron lub tylko te zmienione (ponownie, zależnie od implementacji), więc proces zapisu będzie miał zapisywalną kopię.
Gdy z tego samego rozwidlonych jest wiele procesów, gdy proces „master” zapisuje w pamięci, pozostałe procesy kopiują swoje równoważne strony.


który system to robi? linux używa implementacji kopiowania przy zapisie
brauliobo,

Tak działa kopiowanie przy zapisie ...
Didi Kohen

3
@DavidKohen nie tak działa kopiowanie przy zapisie w jakiejkolwiek jego wersji, o której słyszałem. Nie ma procesu „master”. Jeśli jakikolwiek pojedynczy proces zapisze udostępnione strony, jego kopia zostanie zderzona z prywatną, podczas gdy wszystkie pozostałe procesy będą go nadal udostępniać.
Celada,

1
Myślę, że David Kohen ma rację do pewnego momentu. Jest to jeden ze sposobów implementacji kopiowania przy zapisie. Istotą byłoby to, że przy tym oznaczeniu pisanie na tej stronie uruchomiłoby moduł obsługi błędów strony, który następnie podjąłby odpowiednie działanie, tj. Kopiowanie przy zapisie. Niestety ten szczegół (który byłby specyficzny dla systemu) jest w większości nieistotny dla pytania. Pamiętaj, że CoW ma dwa wymiary: ten widoczny dla procesu i ten, w jaki sposób jądro może go zaimplementować.
0xC0000022L
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.