GNU/Linux >> Znalost Linux >  >> Linux

Který soubor v jádře určuje fork(), vfork()... pro použití systémového volání sys_clone()

fork() a vfork() wrappery v glibc jsou implementovány pomocí clone() systémové volání. Pro lepší pochopení vztahu mezi fork() a clone() , musíme zvážit vztah mezi procesy a vlákny v Linuxu.

Tradičně fork() by duplikovaly všechny prostředky vlastněné nadřazeným procesem a přiřadily kopii podřízenému procesu. Tento přístup vyžaduje značnou režii, která by mohla být k ničemu, pokud dítě okamžitě zavolá exec() . V Linuxu fork() využívá copy-on-write stránky, abyste zdrželi nebo se úplně vyhnuli kopírování dat, která lze sdílet mezi nadřazeným a podřízeným procesem. Jedná se tedy o jedinou režii, která vzniká během normálního fork() je kopírování rodičovských tabulek stránek a přiřazení jedinečné struktury deskriptoru procesu, task_struct , pro dítě.

Linux má také výjimečný přístup k vláknům. V Linuxu jsou vlákna pouze obyčejné procesy, které náhodou sdílejí některé zdroje s jinými procesy. Jedná se o radikálně odlišný přístup k vláknům ve srovnání s jinými operačními systémy, jako jsou Windows nebo Solaris, kde procesy a vlákna představují zcela odlišné druhy bestií. V Linuxu má každé vlákno obyčejných task_struct svůj vlastní, který je náhodou nastaven tak, že sdílí určité zdroje, jako je adresní prostor, s nadřazeným procesem.

flags parametru clone() systémové volání obsahuje sadu příznaků, které indikují, které zdroje, pokud nějaké, by měly sdílet nadřazený a podřízený proces. Procesy a vlákna jsou vytvářeny pomocí clone() , jediným rozdílem je sada příznaků, která je předána clone() .

Normální fork() lze implementovat jako:

clone(SIGCHLD, 0);

Tím se vytvoří úloha, která nesdílí žádné zdroje se svým rodičem a je nastavena na odesílání SIGCHLD signál ukončení rodičovi, když opustí.

Naproti tomu úloha, která sdílí adresní prostor, prostředky souborového systému, deskriptory souborů a obslužné rutiny signálů s nadřazeným prvkem, jinými slovy vlákno , lze vytvořit pomocí:

clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

vfork() je zase implementován prostřednictvím samostatného CLONE_VFORK příznak, který způsobí, že nadřazený proces uspí, dokud jej podřízený proces neprobudí signálem. Podřízený prvek bude jediným vláknem provádění v nadřazeném jmenném prostoru, dokud nezavolá exec() nebo výstupy. Dítěti není dovoleno zapisovat do paměti. Odpovídající clone() volání může být následující:

clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)

Implementace sys_clone() je specifická pro architekturu, ale většina práce se odehrává v do_fork() definováno v kernel/fork.c . Tato funkce volá statické clone_process() , který vytvoří nový proces jako kopii rodiče, ale ještě ho nespustí. clone_process() zkopíruje registry, přiřadí PID nové úloze a buď duplikuje nebo sdílí příslušné části procesního prostředí, jak je specifikováno klonem flags . Když clone_process() vrátí, do_clone() probudí nově vytvořený proces a naplánuje jeho spuštění.


Komponenta zodpovědná za překlad funkcí systémových volání userland do systémových volání jádra pod Linuxem je knihovna libc. V GLibC to knihovna NPTL přesměruje na clone(2) systémové volání.


Linux
  1. Pro jakou pracovní zátěž jste poprvé použili linuxové kontejnery?

  2. Jak příkaz Xdg-open ví, kterou aplikaci použít k otevření souboru?

  3. Rozdíl mezi fork(), vfork(), exec() a clone()

  1. Kde najdu zdrojový kód systémového volání?

  2. Které systémové volání linux používá příkaz ls v linuxu k zobrazení názvu složky/souboru?

  3. Systémové volání fork() a funkce execv

  1. Nejrychlejší systémové volání Linuxu

  2. Proč je v Linuxu potřeba upravovat tabulky systémových volání?

  3. Jak mohu použít rsync se systémem souborů FAT?