GNU/Linux >> Znalost Linux >  >> Linux

Fork vs Clone na 2.6 Kernel Linuxu

fork() bylo původní systémové volání UNIX. Lze jej použít pouze k vytváření nových procesů, nikoli vláken. Je také přenosný.

V Linuxu clone() je nové, všestranné systémové volání, které lze použít k vytvoření nového vlákna provádění. V závislosti na zadaných možnostech se nové spouštění může držet sémantiky procesu UNIX, vlákna POSIX, něčeho mezi tím nebo něčeho úplně jiného (například jiného kontejneru). Můžete zadat všechny druhy voleb, které určují, zda se má sdílet nebo kopírovat paměť, deskriptory souborů, různé jmenné prostory, obslužné rutiny signálů atd.

Od clone() je systémové volání nadmnožiny, implementace fork() obal systémového volání v glibc ve skutečnosti volá clone() , ale to je detail implementace, o kterém programátoři nemusí vědět. Skutečná skutečná fork() systémové volání stále existuje v linuxovém jádře z důvodů zpětné kompatibility, i když se stalo nadbytečným, protože programy, které používají velmi staré verze libc nebo jiné libc kromě glibc, je mohou používat.

clone() se také používá k implementaci pthread_create() Funkce POSIX pro vytváření vláken.

Přenosné programy by měly volat fork() a pthread_create() , nikoli clone() .


Zdá se, že existují dvě clone() věci plovoucí kolem v Linuxu 2.6

Došlo k systémovému volání:

int clone(int (*fn)(void *), void *child_stack,
          int flags, void *arg, ...
          /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );

Toto je "klon()" popsaný provedením man 2 clone .

Pokud si tuto manuálovou stránku přečtete dostatečně blízko, uvidíte toto:

It is actually a library function layered on top of the
underlying clone() system call.

Zdá se, že byste měli implementovat vlákno pomocí "knihovní funkce" navrstvené na matoucím identicky pojmenovaném systémovém volání.

Napsal jsem krátký program:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int
main(int ac, char **av)
{
    pid_t cpid;
    switch (cpid = fork()) {
    case 0:   // Child process
        break;
    case -1:  // Error
        break;
    default:  // parent process
        break;
    }
    return 0;
}

Zkompilováno s:c99 -Wall -Wextra a spustili jej pod strace -f abyste viděli, co systémová volání forking skutečně dělají. Mám to z strace na počítači se systémem Linux 2.6.18 (x86_64 CPU):

20097 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x2b4ee9213770) = 20098
20097 exit_group(0)                     = ?
20098 exit_group(0)

V strace se neobjeví žádné "fork" volání výstup. clone() volání, které se zobrazí v strace output má velmi odlišné argumenty než man-page-clone. child_stack=0 protože první argument je jiný než int (*fn)(void *) .

Zdá se, že fork(2) systémové volání je implementováno z hlediska skutečného clone() , stejně jako "funkce knihovny" clone() je implementován. skutečný clone() má jinou sadu argumentů než man-page-clone.

Zjednodušeně, obě vaše zjevně protichůdná tvrzení o fork() a clone() Jsou správně. Zúčastněný "klon" je však jiný.


fork() je pouze určitá sada příznaků pro systémové volání clone() . clone() je dostatečně obecný na to, aby vytvořil buď "proces" nebo "vlákno" nebo dokonce podivné věci, které jsou někde mezi procesy a vlákny (například různé "procesy", které sdílejí stejnou tabulku deskriptorů souborů).

V podstatě pro každý "typ" informací souvisejících s kontextem provádění v jádře clone() vám dává na výběr mezi aliasem těchto informací nebo jejich kopírováním. Vlákna odpovídají aliasingu, procesy odpovídají kopírování. Zadáním přechodných kombinací příznaků na clone() , můžete vytvářet divné věci, které nejsou vlákna nebo procesy. Obvykle byste to neměli dělat a myslím si, že během vývoje linuxového jádra proběhla určitá debata o tom, zda by mělo umožnit tak obecný mechanismus jako clone() .


Linux
  1. Jak upgradovat jádro na ploše Linuxu

  2. Linux – Kernel:Podpora jmenných prostorů?

  3. Linux – Kernel IP Forwarding?

  1. Linux – Jsou různá jádra Linux/unix zaměnitelná?

  2. Volání funkce uživatelského prostoru z modulu jádra Linuxu

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

  1. Životní cyklus testování linuxového jádra

  2. Linux – poskvrněné jádro v Linuxu?

  3. Linux – metody vyvolání systémového volání v novém jádru?