Čtenáři jako vy pomáhají podporovat MUO. Když provedete nákup pomocí odkazů na našich stránkách, můžeme získat provizi přidružené společnosti. Přečtěte si více.

V Linuxu můžete vytvářet a spravovat vlákna v C/C++ pomocí knihovny vláken POSIX (pthread). Na rozdíl od jiných operačních systémů je v Linuxu malý rozdíl mezi vláknem a procesem. Proto Linux často označuje svá vlákna jako odlehčené procesy.

Pomocí knihovny pthread můžete vytvářet vlákna, čekat na jejich ukončení a explicitně je ukončit.

Historie používání vláken na Linuxu

Před verzí Linuxu 2.6 byla implementace hlavního vlákna LinuxThreads. Tato implementace měla značné limity z hlediska výkonu a synchronizačních operací. Omezení maximálního počtu vláken, které bylo možné spustit, je omezovalo na 1000.

V roce 2003 se týmu vedeném vývojáři z IBM a RedHat podařilo vytvořit Nativní knihovna vláken POSIX (NPTL) dostupný projekt. Poprvé byl představen v RedHat Enterprise verze 3 k vyřešení problémů s výkonem Java Virtual Machine v Linuxu. Knihovna GNU C dnes obsahuje implementace obou mechanismů vláken.

Ani jedno z toho není implementací zelených vláken, které by virtuální stroj spravoval a spouštěl v čistě uživatelském režimu. Když použijete knihovnu pthread, jádro vytvoří vlákno při každém spuštění programu.

V níže uvedených souborech můžete najít informace specifické pro vlákno pro jakýkoli běžící proces /proc//task. Toto je standardní umístění pro informace o procesu pod standard procfs Linux. U jednovláknových aplikací se zdá, že v tomto adresáři je záznam úlohy se stejnou hodnotou jako PID.

Pracovní logika vláken

Vlákna jsou jako procesy aktuálně běžící v operačním systému. V jednoprocesorových systémech (např. mikrokontroléry) jádro operačního systému simuluje vlákna. To umožňuje, aby transakce probíhaly současně prostřednictvím krájení.

Jednojádrový operační systém může skutečně spustit pouze jeden proces najednou. Nicméně, v vícejádrové nebo víceprocesorové systémy, tyto procesy mohou běžet současně.

Vytvoření vlákna v C

Můžete použít pthread_create funkce pro vytvoření nového vlákna. The pthread.h hlavičkový soubor obsahuje definici podpisu spolu s dalšími funkcemi souvisejícími s vlákny. Vlákna používají stejný adresní prostor a deskriptory souborů jako hlavní program.

Knihovna pthread také zahrnuje nezbytnou podporu pro mutex a podmíněné operace potřebné pro synchronizační operace.

Když používáte funkce knihovny pthread, musíte zajistit, aby kompilátor odkazoval na pthread knihovny do spustitelného souboru. V případě potřeby můžete dát kompilátoru pokyn, aby se propojil s knihovnou pomocí -l volba:

gcc -o test test_thread.c -lpthread

Funkce pthread_create má následující podpis:

intpthread_create(pthread_t *vlákno, konstpthread_attr_t *attr, prázdnota *(*start_rutina)(prázdnota *), prázdnota *arg)

Pokud je postup úspěšný, vrátí 0. Pokud dojde k problému, vrátí nenulový kód chyby. Ve výše uvedeném podpisu funkce:

  • The vlákno parametr je typu pthread_t. Vytvořené vlákno bude vždy přístupné s tímto odkazem.
  • The attr parametr umožňuje zadat vlastní chování. Můžete použít řadu funkcí specifických pro vlákno počínaje pthread_attr_ pro nastavení této hodnoty. Možná přizpůsobení jsou zásady plánování, velikost zásobníku a zásady odpojení.
  • start_rutina určuje funkci, kterou bude vlákno spouštět.
  • arg představuje obecnou datovou strukturu předávanou funkci vláknem.

Zde je příklad aplikace:

#zahrnout
#zahrnout
#zahrnout
#zahrnout

prázdnota *pracovník(prázdnota *data)
{
char *jméno = (char*)data;

pro (int i = 0; já < 120; i++)
{
usnout (50000);
printf("Ahoj z názvu vlákna = %s\n", jméno);
}

printf("Vlákno %s hotovo!\n", název);
vrátit seNULA;
}

inthlavní(prázdnota)
{
pthread_t th1, th2;
pthread_create(&th1, NULA, pracovník, "X");
pthread_create(&th2, NULA, pracovník, "Y");
spát(5);
printf("Opuštění hlavního programu\n");
vrátit se0;
}

Typy závitů

Když se vlákno vrátí z hlavní() funkce v aplikaci, všechna vlákna se ukončí a systém uvolní všechny prostředky, které program použil. Stejně tak při ukončení libovolného vlákna pomocí příkazu jako an výstup(), váš program ukončí všechna vlákna.

s pthread_join můžete místo toho počkat na ukončení vlákna. Vlákno používající tuto funkci se zablokuje, dokud očekávané vlákno neskončí. Zdroje, které využívají ze systému, se nevracejí ani v případech, jako je ukončení připojitelných vláken, neplánované CPU nebo dokonce selhání připojení k ptread_join.

Někdy nastanou situace, kdy spojení s pthread_join nedává smysl; pokud například nelze předvídat, kdy vlákno skončí. V tomto případě můžete zajistit, že systém vrátí všechny prostředky automaticky v bodě, kde se vlákno vrací.

Abyste toho dosáhli, měli byste začít příslušná vlákna pomocí ODDĚLENÉ postavení. Při spouštění vlákna ODPOJIT stav lze nastavit pomocí hodnot atributu vlákna nebo pomocí pthread_detach funkce:

intpthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
intpthread_detach(pthread_t vlákno);

Zde je příklad použití pthread_join(). Nahraďte hlavní funkci v prvním programu následujícím:

inthlavní(prázdnota)
{
pthread_t th1, th2;
pthread_create(&th1, NULA, pracovník, "X");
pthread_create(&th2, NULA, pracovník, "Y");
spát(5);
printf("opuštění hlavního programu\n");
pthread_join (th1, NULA);
pthread_join (th2, NULA);
vrátit se0;
}

Když zkompilujete a spustíte program, váš výstup bude:

Ahoj z vlákna Y
Ahoj z vlákna X
Ahoj z vlákna Y
...
Ahoj z vlákna Y
opuštění hlavního programu
Ahoj z vlákna X
...
Ahoj z vlákna X
Vlákno X hotovo!
Ahoj z vlákna Y
Vlákno Y hotovo!

Ukončení vlákna

Vlákno můžete zrušit voláním pthread_cancel a předat odpovídající pthread_t id:

intpthread_cancel(pthread_t vlákno);

Můžete to vidět v akci v následujícím kódu. Opět pouze hlavní funkce je jiná:

inthlavní(prázdnota)
{
pthread_t th1, th2;
pthread_create(&th1, NULA, pracovník, "X");
pthread_create(&th2, NULA, pracovník, "Y");
spát(1);
printf("> Rušení vlákna Y!!\n");
pthread_cancel (th2);
usnout (100000);
printf("> Rušení vlákna X!\n");
pthread_cancel (th1);
printf("opuštění hlavního programu\n");
vrátit se0;
}

Proč jsou vlákna vytvořena?

Operační systémy se vždy snaží spouštět vlákna na jednom nebo více CPU, buď ze seznamu vytvořeného uživatelem nebo ze seznamu vláken vytvořeného uživatelem. Některá vlákna nemohou běžet, protože čekají na vstupní/výstupní signál z hardwaru. Mohou také čekat dobrovolně, čekat na odpověď z jiného vlákna nebo je blokuje jiné vlákno.

Prostředky, které přidělujete vláknům, která vytvoříte, můžete upravit pomocí pthread. Může to být vlastní plánovací politika nebo si můžete vybrat plánovací algoritmy, jako je FIFO nebo Round-robin, pokud si to přejete.