Różnica między fork (), vfork (), exec () i clone()

Szukałem różnicy między tymi czterema w Google i spodziewałem się, że będzie ogromna ilość informacji na ten temat, ale naprawdę nie było żadnego solidnego porównania między czterema połączeniami.

Zacząłem próbować skompilować rodzaj podstawowego spojrzenia na różnice między tymi wywołaniami systemowymi i oto, co mam. Czy wszystkie te informacje są poprawne/czy pominąłem coś ważnego ?

Fork : wywołanie fork zasadniczo tworzy duplikat bieżącego proces, identyczny niemal pod każdym względem(nie wszystko jest kopiowane np. przez ograniczenia zasobów w niektórych implementacjach, ale chodzi o to, aby stworzyć jak najbardziej zbliżoną kopię).

Nowy proces (potomek) otrzymuje inny identyfikator procesu (PID) i ma PID starego procesu (rodzica) jako jego macierzysty PID (PPID). Ponieważ oba procesy uruchamiają teraz dokładnie ten sam kod, mogą stwierdzić, który jest który po kodzie zwrotnym forka-dziecko otrzymuje 0, rodzic otrzymuje PID dziecko. To wszystko, oczywiście, zakładając, że wywołanie fork działa - jeśli nie, nie zostanie utworzone żadne dziecko, a rodzic otrzyma kod błędu.

Vfork : podstawowa różnica między vfork i fork polega na tym, że gdy nowy Proces jest tworzony za pomocą vfork(), proces macierzysty jest tymczasowo zawieszony, a proces potomny może pożyczyć rodzicowi przestrzeń adresową. Ten dziwny stan rzeczy trwa do momentu zakończenia procesu potomnego lub wywołania execve (), w którym to momencie rodzic proces trwa.

Oznacza to, że proces potomny vfork() musi być ostrożny, aby uniknąć nieoczekiwanej modyfikacji zmiennych procesu macierzystego. W szczególności, proces potomny nie może powrócić z funkcji zawierającej wywołanie vfork () i nie może wywołać exit () (jeśli musi zakończyć działanie, powinien użyć _exit (); w rzeczywistości jest to również prawdą dla potomka normalnego fork ()).

Exec : wywołanie exec jest sposobem na zastąpienie całego bieżącego procesu nowym programem. Ładuje programuje do bieżącej przestrzeni procesowej i uruchamia ją z punktu wejścia. exec () zastępuje bieżący proces plikiem wykonywalnym wskazywanym przez funkcję. Kontrola nigdy nie powraca do oryginalnego programu, chyba że wystąpi błąd exec ().

Clone : Clone, jako fork, tworzy nowy proces. W przeciwieństwie do forka, wywołania te pozwalają procesowi potomnemu na współdzielenie części kontekstu wykonania z procesem wywołującym, takich jak przestrzeń pamięci, tabela deskryptorów plików i tabela sygnału pomocnicy.

Gdy proces potomny jest tworzony za pomocą clone, wykonuje aplikację funkcyjną fn (arg). (Różni się to od fork, gdzie wykonywanie w potomku jest kontynuowane od punktu oryginalnego wywołania fork.) Argument fn jest wskaźnikiem do funkcji, która jest wywoływana przez proces potomny na początku jego wykonania. Argument arg jest przekazywany do funkcji fn.

Gdy aplikacja funkcji fn(arg) powróci, proces potomny zostanie zakończony. Liczba całkowita zwrócona przez fn jest kodem zakończenia procesu potomnego. Proces potomny może również zakończyć się jawnie przez wywołanie exit(2) lub po otrzymaniu sygnału krytycznego.

Formularz Informacji:

Dzięki za poświęcenie czasu na przeczytanie tego ! :)

Author: codeforester, 2011-02-01

5 answers

  • vfork() jest przestarzałą optymalizacją. Przed dobrym zarządzaniem pamięcią, fork() zrobiłem pełną kopię pamięci rodzica, więc było to dość drogie. ponieważ w wielu przypadkach po {[1] } następowało exec(), które odrzucało aktualną mapę pamięci i tworzyło nową, był to niepotrzebny wydatek. Obecnie fork() nie kopiuje pamięci; jest po prostu ustawiona jako "Kopiuj przy zapisie", więc fork()+exec() jest tak samo wydajny jak vfork()+exec().

  • clone() jest syscall używany przez fork(). z niektóre parametry, tworzy nowy proces, z innymi, tworzy wątek. różnica między nimi polega na tym, które struktury danych (przestrzeń pamięci, stan procesora, stos, PID, otwarte pliki itp.) są współdzielone, czy nie.

 134
Author: Javier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-31 21:42:05
  • execve() zastępuje bieżący obraz wykonywalny innym obrazem załadowanym z pliku wykonywalnego.
  • fork() tworzy proces potomny.
  • {[2] } jest historycznie zoptymalizowaną wersją fork(), przeznaczoną do użycia, gdy execve() jest wywoływana bezpośrednio po fork(). Okazało się, że działa dobrze w systemach innych niż MMU (gdzie fork() nie może działać wydajnie) i kiedy fork()ing procesy z ogromnym śladem pamięci, aby uruchomić jakiś mały program (pomyśl o Javie Runtime.exec()). POSIX ustandaryzował posix_spawn() w celu zastąpienia tych ostatnich dwóch bardziej nowoczesnych zastosowań vfork().
  • posix_spawn() robi odpowiednik fork()/execve(), a także pozwala na żonglowanie fd pomiędzy. Ma zastąpić fork()/execve(), głównie dla platform spoza MMU.
  • pthread_create() tworzy nowy wątek.
  • clone() jest wywołaniem specyficznym dla Linuksa, które może być użyte do implementacji wszystkiego od fork() do pthread_create(). Daje dużo kontroli. Zainspirowany rfork().
  • rfork() to połączenie specyficzne dla planu-9. To ma być Rodzajowy wywołanie, pozwalające na kilka stopni współdzielenia, pomiędzy Pełnymi procesami i wątkami.
 67
Author: ninjalj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-12 18:49:58
  1. fork() - tworzy nowy proces potomny, który jest kompletną kopią procesu nadrzędnego. Procesy potomne i nadrzędne używają różnych wirtualnych przestrzeni adresowych, które początkowo są wypełniane przez te same strony pamięci. Następnie, w miarę wykonywania obu procesów, wirtualne przestrzenie adresowe zaczynają się coraz bardziej różnić, ponieważ system operacyjny wykonuje leniwe kopiowanie stron pamięci, które są pisane przez jeden z tych dwóch procesów i przypisuje niezależne kopie zmodyfikowanych stron pamięci dla każdego procesu. Technika ta nazywana jest Copy-On-Write (COW).
  2. vfork() - tworzy nowy proces potomny, który jest "szybką" kopią procesu nadrzędnego. W przeciwieństwie do wywołania systemowego fork(), procesy potomne i nadrzędne mają tę samą wirtualną przestrzeń adresową. Uwaga! Używając tej samej wirtualnej przestrzeni adresowej, zarówno rodzic, jak i dziecko używają tego samego stosu, wskaźnika stosu i wskaźnika instrukcji, jak w przypadku klasycznego fork()! Aby zapobiec niechcianej ingerencji rodzica proces potomny, który używa tego samego stosu, jest wstrzymywany do momentu wywołania exec() (utworzenia nowej wirtualnej przestrzeni adresowej i przejścia do innego stosu) lub _exit() (zakończenia wykonywania procesu). vfork() jest optymalizacją fork() dla modelu "fork-and-exec". Może być wykonywana 4-5 razy szybciej niż fork(), ponieważ w przeciwieństwie do fork() (nawet z krową trzymaną w umyśle), implementacja vfork() wywołania systemowego nie obejmuje utworzenia nowego adresu miejsce (przydzielanie i zakładanie nowych katalogów stron).
  3. clone() - tworzy nowy proces potomny. Różne parametry tego wywołania systemowego określają, które części procesu nadrzędnego muszą zostać skopiowane do procesu podrzędnego i które części będą współdzielone między nimi. W rezultacie to wywołanie systemowe może być używane do tworzenia wszelkiego rodzaju jednostek wykonawczych, począwszy od wątków, a skończywszy na całkowicie niezależnych procesach. W rzeczywistości, clone() wywołanie systemowe jest bazą, która jest używana do implementacja pthread_create() i całej rodziny wywołań systemowych fork().
  4. exec() - resetuje całą pamięć procesu, wczytuje i parsuje podany plik binarny wykonywalny, ustawia nowy stos i przekazuje kontrolę do punktu wejścia załadowanego pliku wykonywalnego. To wywołanie systemowe nigdy nie zwraca kontroli do dzwoniącego i służy do ładowania nowego programu do już istniejącego procesu. To wywołanie systemowe z wywołaniem systemowym fork() razem tworzą klasyczny model zarządzania procesami UNIX o nazwie "fork-and-exec".
 28
Author: ZarathustrA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-12 00:13:33

Fork(),vfork() i clone() wywołują do_fork (), aby wykonać prawdziwą pracę, ale z różnymi parametrami.

asmlinkage int sys_fork(struct pt_regs regs)
{
    return do_fork(SIGCHLD, regs.esp, &regs, 0);
}

asmlinkage int sys_clone(struct pt_regs regs)
{
    unsigned long clone_flags;
    unsigned long newsp;

    clone_flags = regs.ebx;
    newsp = regs.ecx;
    if (!newsp)
        newsp = regs.esp;
    return do_fork(clone_flags, newsp, &regs, 0);
}
asmlinkage int sys_vfork(struct pt_regs regs)
{
    return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0);
}
#define CLONE_VFORK 0x00004000  /* set if the parent wants the child to wake it up on mm_release */
#define CLONE_VM    0x00000100  /* set if VM shared between processes */

SIGCHLD means the child should send this signal to its father when exit.

Dla fork, dziecko i ojciec mają niezależną tabelę stron maszyny wirtualnej, ale ponieważ wydajność, fork tak naprawdę nie skopiuje żadnych stron, po prostu ustawia wszystkie strony do odczytu tylko dla procesu potomnego. Więc kiedy proces potomny chce coś napisać na tej stronie, zdarza się wyjątek strony i kernel przydziela nową stronę sklonowaną ze starej strony z uprawnieniami do zapisu. To się nazywa "Kopiuj przy zapisie".

Dla vfork, pamięć wirtualna jest dokładnie przez dziecko i ojca - - - tylko dlatego, ojciec i dziecko nie mogą być obudzeni jednocześnie, ponieważ będą wpływać na siebie nawzajem. Tak więc ojciec uśpi się na końcu "do_fork ()" i obudzi się, gdy dziecko wywoła exit () lub execve (), ponieważ wtedy będzie właścicielem nowej tabeli stron. Oto kod (w do_fork ()), który ojciec śpi.

if ((clone_flags & CLONE_VFORK) && (retval > 0))
down(&sem);
return retval;

Oto kod(w mm_release() wywołany przez exit() i execve ()), który budzi Ojcze.

up(tsk->p_opptr->vfork_sem);

Dla sys_clone () jest bardziej elastyczna, ponieważ można do niej wprowadzić dowolne clone_flags. Tak więc pthread_create () wywołuje to wywołanie systemowe z wieloma clone_flags:

Int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM);

Podsumowanie: fork(),vfork() i clone() będą tworzyć procesy potomne z innym montowaniem współdzielenia zasobów z procesem macierzystym. Możemy również powiedzieć, że vfork() i clone () mogą tworzyć wątki (w rzeczywistości są to procesy, ponieważ mają niezależne task_struct), ponieważ dzielą tabelę stron maszyny Wirtualnej z procesem macierzystym.

 5
Author: user991800,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-09 10:58:55

W fork(), proces potomny lub rodzic będzie uruchamiany na podstawie wyboru procesora.. Ale w vfork(), na pewno child uruchomi się jako pierwszy. gdy dziecko zostanie zakończone, rodzic uruchomi się.

 -3
Author: Raj Kannan B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-09 04:23:27