Czy fork () natychmiast kopiuje całą stertę procesów w systemie Linux?


30

fork()Wywołanie systemowe klonuje proces dziecko od uruchomionego procesu. Dwa procesy są identyczne, z wyjątkiem ich PID.

Oczywiście, jeśli procesy tylko czytają ze swoich stosów, a nie zapisują, kopiowanie sterty byłoby ogromnym marnotrawstwem pamięci.

Czy cała kupa procesu została skopiowana? Czy jest zoptymalizowany w taki sposób, że tylko pisanie wyzwala kopię sterty?

Odpowiedzi:


19

Całość stanowi fork()realizowany jest za pomocą mmap / kopiowania przy zapisie.

Wpływa to nie tylko na stertę, ale także na biblioteki współdzielone, stos, obszary BSS.

Co, nawiasem mówiąc, oznacza, że ​​rozwidlenie jest niezwykle lekką operacją, dopóki wynikowe 2 procesy (nadrzędny i podrzędny) faktycznie nie zaczną zapisywać w zakresach pamięci. Ta funkcja w znacznym stopniu przyczynia się do niszczenia bomb widelcowych - kończy się zbyt wiele procesów, zanim jądro zostanie przeciążone replikacją i różnicowaniem stron.

Trudno będzie znaleźć w nowoczesnym systemie operacyjnym przykład operacji, w której jądro wykonuje kopię drukowaną (wyjątek stanowią sterowniki urządzeń) - po prostu znacznie, znacznie łatwiej i wydajniej jest korzystać z funkcji VM.

Nawet execve()jest w zasadzie „prosze mapować plik binarny / ld.so / whatnot, a następnie wykonać” - a VM obsługuje faktyczne ładowanie procesu do pamięci RAM i wykonywanie. Lokalne niezainicjowane zmienne są w końcu kształtowane na „stronie zerowej” - specjalna strona tylko do odczytu, która zawiera zera, lokalne zmienne inicjalizowane są w końcu kształtowane (ponownie kopiowanie podczas zapisu, ponownie) z samego pliku binarnego, itp.


Jednym godnym uwagi wyjątkiem są procesy Java. Wyszukaj „rozwidlenie pamięci Java”, a znajdziesz dziesiątki problemów wpływających na JVM dużego serwera lub osadzoną JVM próbujących wykonać małe polecenie powłoki i niefortunnie zawieszających się w wyjątku „Nie można przydzielić pamięci” (są to tylko losowe łącza, ten problem ma charakter systemowy do środowisk Java). Ta odpowiedź SO oskarża moduł zbierający śmieci JVM i kompilator JIT o powstrzymywanie udostępniania pamięci procesów.
WhiteWinterWolf

24

Jądro Linux implementuje funkcję Copy-on-Write, gdy fork()jest wywoływana. Po uruchomieniu syscall strony udostępnione przez rodzica i dziecko są oznaczone jako tylko do odczytu.

Jeśli zapis jest wykonywany na stronie tylko do odczytu, jest on następnie kopiowany, ponieważ pamięć nie jest już identyczna między dwoma procesami. Dlatego, jeśli wykonywane są tylko operacje odczytu, strony w ogóle nie zostaną skopiowane.


1
+1 dzięki! 1. Czy możesz podać linki referencyjne? 2. Czy kupa jest kopiowana w całości lub w części?
Adam Matan

4
2. - Na stronach :) Jądro bardzo mało rozumie, czym jest „sterta” - dla jądra jest to tylko garstka zmapowanych prywatnych stron, które alokatorzy libc potrafią obsłużyć.
qdot

Czy to naprawdę bomba widełkowa? Wydaje mi się, że zamiast rozwidlać bieżący proces, kod ten utworzy więcej instancji tego samego programu, które wykonują się od początku, niż od następnej instrukcji po fork()wywołaniu.
sherrellbc

@mmk FYI, byłem dość zaskoczony twoją „Ciekawą notatką:”, więc przetestowałem (na Linuksie 3.2.0), aby zobaczyć i nie wydaje się to prawdą. Kiedyś /proc/self/pagemapokreślałem adres wirtualny do fizycznego mapowania strony na potrzeby testu. Tak jak się spodziewałem, jeśli wnuk i tylko wnuczek pisze udostępnioną stronę, to rodzic i pierwotne dziecko nadal ją udostępniają. Tylko wnuk kończy się na prywatnej kopii.
Celada,

@Celada. Hmm Przeczytałem to gdzieś i nie pamiętam wersji jądra, do której się odnosił (prawdopodobnie starszej?), Więc może już nie być poprawna.
mmk

10

Linux wykonuje kopiowanie przy zapisie. W miarę forktworzenia nowego procesu przydzielone strony są oznaczane jako tylko do odczytu i udostępniane między rodzicem a dzieckiem. Gdy którakolwiek z nich próbuje zmodyfikować stronę, generowany jest błąd strony, który powoduje skopiowanie strony i odpowiednie dostosowanie tabeli stron.

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.