Nie mam dużego doświadczenia, po prostu staram się zaangażować w procesy, w jaki sposób interpretują sprzęt z poziomu użytkownika.
Kiedy więc polecenie jest uruchamiane z powłoki, fork()
dziedziczy proces potomny i exec()
ładuje proces potomny do pamięci i wykonuje.
- Jeśli proces potomny zawiera wszystkie atrybuty procesu macierzystego (który jest procesem oryginalnym), to jaka jest potrzeba tego procesu potomnego? Oryginalny proces mógł również zostać załadowany do pamięci.
- Czy to
fork
iexec
koncepcja ma zastosowanie do wszystkich programów wykonywalnych w systemie UNIX? Podobnie jak w przypadku skryptu powłoki, czy tylko dla poleceń? Czy dotyczy to również wbudowanych poleceń powłoki? - Kiedy używana jest koncepcja kopiowania przy zapisie, jeśli wykonam polecenie / skrypt?
Przepraszam, że zadawałem wiele pytań na raz, ale wszystkie te pytania przychodzą mi do głowy od razu, gdy myślę o wykonaniu polecenia.
Odpowiedzi:
Nie do końca.
fork()
klonuje bieżący proces, tworząc identyczne dziecko.exec()
ładuje nowy program do bieżącego procesu, zastępując istniejący.Jest to konieczne, ponieważ proces nadrzędny nie chce się jeszcze kończyć; chce, aby nowy proces rozpoczął się i zrobił coś w tym samym czasie, co nadal będzie wykonywany.
W przypadku poleceń zewnętrznych powłoka robi
fork()
tak, że polecenie działa w nowym procesie. Wbudowane są uruchamiane bezpośrednio przez powłokę. Innym godnym uwagi poleceniem jestexec
przekazanie powłokiexec()
zewnętrznemu programowi bez uprzedniegofork()
wejścia. Oznacza to, że sama powłoka została zastąpiona nowym programem, a więc nie ma już możliwości powrotu do tego programu po wyjściu. Jeśli powiesz,exec true
to/bin/true
zastąpi twoją powłokę i natychmiast wyjdzie, nie pozostawiając nic w twoim terminalu, więc się zamknie.W epoce kamienia łupanego
fork()
musiałem skopiować całą pamięć z procesu wywoływania do nowego procesu. Kopiuj przy zapisie to optymalizacja, w której tabele stron są skonfigurowane w taki sposób, że dwa procesy zaczynają współużytkować całą tę samą pamięć, a tylko strony, na których zapisany jest dowolny proces, są kopiowane w razie potrzeby.źródło
cd
lubread
mogą działać. Brak rozwidlania sprawia, że wbudowane funkcje są znacznie szybsze niż polecenia zewnętrzne.execve()
celu nałożenia się innym kodem.fork()
iexec()
mają zastosowanie do wszystkich plików wykonywalnych - w rzeczywistości wraz z argc i argv, a potoki, fork i exec są tym, co odróżnia Uniksa od innych systemów operacyjnych. Istnieje kilka specjalizacji lub uogólnieńfork()
, takich jak BSDvfork()
, Plan 9'srfork()
i Linux 'clone()
, ale główna zasada pozostaje taka sama.malloc()
, a nawet zmienne o zasięgu statycznym lub globalnym) mogą być „kopiuj przy zapisie”. Kiedy proces potomny zostanie utworzony za pomocąfork()
wywołanie, jądro skonfigurowałoby proces potomny tak, aby miał dokładnie te same strony pamięci co stos i stos jak proces nadrzędny. Jeśli sprzęt (jednostka zarządzania pamięcią) wykryje zapis stosu lub stosu, jądro otrzyma nową fizyczną stronę pamięci, skopiuje stronę rodzica na nową stronę i zamapuje tę nową stronę na stosie lub stosie procesu potomnego. Stanowi to optymalizację, ponieważ jądro poświęca mniej czasu na konfigurowanie odwzorowań stron niż na całkowite skopiowanie stosu i sterty do procesu potomnego.źródło
Na to pytanie bardzo ilustracyjnie odpowiada spojrzenie na najwcześniejsze implementacje uniksowe, które musiały działać przy poważnych ograniczeniach pamięci i miały tylko jeden proces w pamięci / przestrzeni adresowej na raz.
Wielozadaniowość została osiągnięta poprzez zamianę procesu na dysk i zamianę innego procesu.
Teraz
fork
wywołanie systemowe było prawie takie samo: zamieniło proces na dysk, ale zamiast zamiany innego procesu, podało w pamięci kopię innego identyfikatora procesu i wróciło do niego. I to był odpowiedni moment, aby ten procesexec
w końcu zdecydował się na inny plik wykonywalny.fork
+ wexec
ten sposób nie poniósł zauważalnego obciążenia związanego z odradzaniem: i tak musiałeś zamienić swój proces na dysk, a stary obraz procesu i tak miałeś w realnych lokalizacjach pamięci.Wraz ze wzrostem ilości dostępnej pamięci i jednostek zarządzania pamięcią oraz wieloma procesami w pamięci, początkowo znikomy koszt rozwidlenia stał się nieco bardziej uciążliwy dla niektórych architektur: tak się
vfork
narodziło.źródło
Aby uczynić to tak łatwym do zrozumienia, jak to możliwe, skorzystam z analogii. Upieczmy ciasto!
Chwytamy książkę kucharską, zaczynamy czytać i osiadamy na truskawkowym cieście rabarbarowym (moim ulubionym) z ręcznie robioną skórką. Prawie wszystko, czego potrzebujemy, to jajka i owoce, ale ponieważ mieszkamy na farmie, a owoce są sezonowe, nie stanowi to problemu. problem polega na tym, że piekarnik jest zepsuty i nie ma czasu na zrobienie wszystkiego. Czy nie byłoby miło mieć więcej niż jednego ze mnie?
fork () na ratunek. Teraz jest mnie dwóch. i oboje idziemy do kuchni, żeby zacząć robić ciasto na ciasto. ups. Patrzymy więc na powrót z widelca. Mam dużą liczbę, a on zero, więc idę do kuchni, a on idzie do kurnika i ogrodu. Gdy przechodzę obok piekarnika, ponownie widelcem () patrzę na wartość zwracaną: bummer mam zero. Kontynuuje mąkę, gdy patrzę na zepsuty piekarnik. Otwieram drzwi, Bez światła, zamykam drzwi. Czy ktoś wie, jak naprawić piekarnik?
exec () na ratunek. Sięgam po woltomierz na pasku narzędzi, żarówka może być diagnostyczna, więc sprawdzam moc, rzeczywiście wyłamał się wyłącznik, łatwa naprawa. podchodząc do panelu wyłącznika widzę mężczyznę zbierającego rabarbar. Fuj! Wolę czekoladowe ciasto jedwabne.
źródło