Procesy vs (rozwidlone)

9

Aplikacje Linux generalnie rozwidlają, a następnie wykonują (za pomocą execve ()), ale aplikacje Java i niektóre Apache MPM używają wątków. Jeśli rozwidlasz, używa fork + exec do odrodzenia procesu, jaka jest wersja wysokiego poziomu do wątkowania? W jaki sposób JVM lub Worker MPM spawnuje wątki?

Gregg Leventhal
źródło
2
Sprawdź Stackoverflow. Istnieje kilka pytań i odpowiedzi, które wyjaśniły część tego.
Henk Langeveld

Odpowiedzi:

13

Idea wątków i procesów jest mniej więcej taka sama: rozwidlasz ścieżkę wykonania. W przeciwnym razie wątki i procesy różnią się między innymi pamięcią. Tj. Procesy mają inną przestrzeń VM, a wątki współużytkują wszystko, co istniało przed podziałem.

Zarówno praca nad wątkami, jak i rozwidlanie za pomocą wywołania clone () (klon man 2):

W przeciwieństwie do fork (2), clone () pozwala procesowi potomnemu współdzielić części jego kontekstu wykonania z procesem wywołującym, takim jak przestrzeń pamięci, tabela deskryptorów plików i tabela programów obsługi sygnałów. (Zauważ, że na tej stronie podręcznika „proces wywoływania” zwykle odpowiada „procesowi nadrzędnemu”. Ale zobacz opis CLONE_PARENT poniżej.)

Głównym zastosowaniem clone () jest implementacja wątków: wielu wątków kontroli w programie, które działają jednocześnie w przestrzeni pamięci współużytkowanej.

Różnice wynikają z flag przekazywanych do clone (). Jak widać ze strony man, fork i threading to tylko zestaw predefiniowanych parametrów do klonowania (). Jednak można również robić z nim niestandardowe rzeczy.

V13
źródło
1
Uhm? Co? Przeczytaj ponownie prawie każdą książkę na ten temat, ponieważ osobna przestrzeń pamięci dla procesów jest czymś wielkim. Pomaga także „złapać” kod, który ulega awarii, podczas gdy jądro po prostu zabija proces, w którym pojedynczy wątek przechodzi w stan szaleństwa / wtargnięcia.
0xC0000022L
3
@ 0xC0000022L twój argument nie jest sprzeczny z odpowiedzią, jak mi się wydaje.
Ruslan
1
@ Ruslan: Zaczynam się różnić: „Pomysł [...] jest mniej więcej taki sam”? Ideą wątków jest rzeczywiście współbieżność, ale dla procesów jest to zupełnie inna historia.
0xC0000022L
4
@ 0xC0000022L Przegapiłeś ważną część odpowiedzi V13: „
Rozwidlasz
@Izkata: wcale nie. Po prostu twierdzę, że to nie jest poprawne twierdzenie.
0xC0000022L
8

Większość nie Unixowych wieloprocesorowych systemów operacyjnych (OS) używa wywołania „spawn ()” lub czegoś podobnego w celu wygenerowania nowego procesu lub przepływu kontrolnego systemu operacyjnego. Spawn () jest zwykle bardzo złożonym wywołaniem, z wieloma opcjami i dużym narzutem. Jedną z innowacji Uniksa było zapewnienie znacznie niższego ogólnego sposobu tworzenia procesów - fork (). Unix zadbał o wiele niezbędnych opcji spawn (), zezwalając na dowolne ilości przetwarzania przed drugą połową spawn () za pomocą exec ().

Ponieważ Unix i jego warianty były coraz częściej stosowane, okazało się, że użyteczne jest tworzenie niskiego narzutu, które było wykorzystywane. W rzeczywistości używano go tak bardzo, że ludzie chcieli jeszcze niższych ogólnych sposobów tworzenia procesów i tak narodził się pomysł „wątków”. Początkowo wątki były obsługiwane całkowicie przez proces inicjujący (a programy takie jak JVM mogą to robić z „zielonymi wątkami”); ale obsługa planowania wielowątkowego jest trudna i często była wykonywana niepoprawnie. Jest więc łatwiejszy, pośredni sposób wykonywania wątków, w którym system operacyjny obsługuje planowanie, ale narzut jest oszczędzany przez (zwykle) współdzielenie przestrzeni adresowej między wątkami.

Odpowiedź na twoje pytanie jest trudna, ponieważ istnieje kilka różnych, ale powiązanych ze sobą pojęć, które wszystkie są „wątkami”, a dla szczegółów potrzebujesz przymiotnika, aby opisać, do którego się odwołujesz. Z drugiej strony zrozumienie różnic prawdopodobnie doprowadzi cię do konkretnej odpowiedzi, jakiej chcesz. Wyszukaj takie rzeczy jak „lekkie procesy”, „wątki użytkownika” i „rfork ()”, aby uzyskać więcej informacji.

mpez0
źródło
1
„obsługa szeregowania wielowątkowego jest trudna i często była wykonywana niepoprawnie” potrzebne jest cytowanie. Implementacja wątków przestrzeni użytkownika nie stanowi problemu. Problem z wątkami przestrzeni użytkownika polega na tym, że jeśli wątek wykonuje blokujące wywołanie systemowe, wszystkie wątki zostają zablokowane. Jedynym sposobem na uniknięcie tego jest użycie wątków na poziomie systemu.
Bakuriu
1
Co ciekawe, Windows nie uwzględnił tej innowacji Uniksa: nie ma, CreateProcess()ale nic podobnego do fork().
Ruslan
2
@ Bakuriu - poszukaj dowolnego z wielu artykułów na temat budowania harmonogramów wieloprocesowych, utrzymywania sprawiedliwości, unikania głodu, obsługi priorytetów itp. Wdrażanie przestrzeni użytkownika nie jest, jak mówisz, problemem. Planowanie nietrywialnych przykładów jest trudne.
mpez0
@ Ruslan: można rozwidlać w systemie Windows, to po prostu nie jest częścią Win32 API. Przeczytaj „Natywny interfejs API Windows NT / 2000” Nebbett. Ma implementację, która naśladuje fork().
0xC0000022L
3

Wątki i rozwidlenie to tak naprawdę dwie różne koncepcje, z których obie istnieją w systemach Unix / Linux (i obie mogą być używane w C / C ++).

Idea fork () jest (bardzo zasadniczo) stworzeniem osobnego procesu, który ma ten sam kod wykonania co proces nadrzędny i który rozpoczyna wykonywanie od linii rozwidlenia. Celem użycia widelców z funkcjami exec jest to, że funkcje exec zamykają proces, który je wywołał, kiedy się kończą. Tak więc zwykle rozwidlasz się, otrzymując PID każdego procesu (dziecko zawsze ma wartość 0) i każesz rodzicowi czekać, aż dziecko zakończy wykonywanie funkcji exec.

Wątki są używane do równoległości (pamiętaj, że rodzic czeka na dziecko, zwykle w rozwidlonym programie). Wątek, taki jak pthread w C / C ++ (wykonaj wyszukiwanie w Google), będzie działał równolegle z głównym procesem i może współdzielić zmienne globalne i funkcje globalne z oryginalnym programem. Ponieważ wątki Java zachowują się podobnie, wyobrażam sobie, że działają one bardziej jak te wątki niż proces rozwidlania.

Zasadniczo istnieje różnica między rozwidleniem a gwintowaniem. Robią wyraźnie różne rzeczy (choć wydają się podobne). Pojęcia te mogą być trudne do zrozumienia, ale możesz nauczyć się ich poprzez (obszerne) badania, jeśli masz szczerą chęć ich zrozumienia.

EDYCJA 1

Zapoznaj się z przykładami wywoływania i używania widelców i wątków. Zwróć uwagę na zachowanie funkcji exec i ich wpływ na główny program.

http://www.jdembrun.com:4352/computerScience/forkVSthread.zip

jaredad7
źródło
2
Widelec (z exec lub bez) może być również użyty do równoległości. Nie jestem pewien, co masz na myśli przez „funkcje exec zamykają proces, który je wywołał, gdy się kończą”, exec już dawno skończył działać po zakończeniu procesu. Również pthreadto API, a nie realizacja wątek.
Mat
Jeśli chodzi o rozwidlenie, cytuję mojego nauczyciela systemu operacyjnego. Zgodnie z tym, co nam powiedział, tak, rozwidlenia można użyć do równoległego działania, ale jeśli użyłaby funkcji exec, byłaby to ostatnia. Jeśli chodzi o pthread, miał to być przykład.
jaredad7
Exec będzie ostatnim wywołaniem w kodzie wywołującym, a nie ostatnią instrukcją procesu rozwidlenia. Rozwidlony proces działałby po uruchomieniu kodu exec.
Mat
Twoje komentarze skłoniły mnie do przetestowania tych rzeczy. Napisałem kilka programów c ++, które demonstrują zachowanie funkcji exec i ich wpływ na programy, gdy są używane w rozwidleniach vs. wątkach. Zobacz powyższą edycję.
jaredad7
Obawiam się, że większość ludzi nie będzie chciała tego pobierać. Również twoje przykłady nie ilustrują interesujących różnic między modelami, które są głównie związane z udostępnianiem (lub nie) przestrzeni adresowej.
Mat
1

Zarówno JVM, jak i Apache MPM polegają na jądrze dla wątków natywnych. Oznacza to, że używają systemu operacyjnego do ich planowania. Oczywiście oba potrzebują własnego API do śledzenia rzeczy.

Stackoverflow ma już kilka pytań na ten temat:

  1. Rodzime wątki JVM , sprawdź tę odpowiedź, aby uzyskać więcej szczegółów.

  2. Apache ma dwa typy MPM: Prefork, z jednym procesem na wątek oraz Worker, który obsługuje wiele wątków: Apache MPM . Sprawdź odniesienie docodebucket

Henk Langeveld
źródło
1

Jeśli rozwidlasz, używa fork + exec do odrodzenia procesu, jaka jest wersja wysokiego poziomu do wątkowania? W jaki sposób JVM lub Worker MPM spawnuje wątki?

Jest to specyficzne dla platformy, ale na Linuksie i przypuszczam, że wiele innych systemów zgodnych z POSIX używa lokalnej implementacji pthreads , interfejsu API wątkowości użytkownika. Na przykład:

#include <pthread.h>

pthread_t tid;
pthread_create(&tid, NULL, somefunc, NULL);

Rozpoczyna nowe wywołanie wątku somefuncjako pierwszy punkt wykonania.

Możesz także tworzyć wątki - różne od widelców, ponieważ współużytkują tę samą globalną przestrzeń pamięci sterty procesu nadrzędnego, zamiast uzyskiwać jej duplikat (ale pamiętaj, że każdy wątek wykonuje się z własną niezależną pamięcią stosu ) - z clone()wywołaniem systemowym, na którym zbudowane są pthreads.

Złotowłosa
źródło