GNU/Linux >> Znalost Linux >  >> Linux

Jak vytvářet vlákna v Linuxu (pomocí ukázkového programu C)

V části I série Linux Threads jsme diskutovali o různých aspektech souvisejících s vlákny v Linuxu.

V tomto článku se zaměříme na to, jak se vlákno vytváří a identifikuje. Představíme také příklad pracovního programu v C, který vysvětlí, jak provádět základní programování ve vláknech.

Linux Threads Series:část 1, část 2 (tento článek), část 3.

Identifikace vlákna

Stejně jako je proces identifikován pomocí ID procesu, je vlákno identifikováno ID vlákna. Ale zajímavé je, že podobnost mezi těmito dvěma končí zde.

  • ID procesu je jedinečné v celém systému, kde je ID vlákna jedinečné pouze v kontextu jednoho procesu.
  • ID procesu je celočíselná hodnota, ale ID vlákna nemusí být nutně celočíselná hodnota. Klidně to může být struktura
  • ID procesu lze vytisknout velmi snadno, zatímco ID vlákna není snadné vytisknout.

Výše uvedené body poskytují představu o rozdílu mezi ID procesu a ID vlákna.

ID vlákna je reprezentováno typem ‚pthread_t‘. Jak jsme již probrali, že ve většině případů je tento typ strukturou, musí existovat funkce, která dokáže porovnat dvě ID vláken.

#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);

Jak tedy vidíte, výše uvedená funkce přebírá dvě ID vlákna a vrací nenulovou hodnotu, pokud jsou obě ID vlákna stejná, jinak vrátí nulu.

Jiný případ může nastat, když vlákno bude chtít znát své vlastní ID vlákna. Pro tento případ poskytuje požadovanou službu následující funkce.

#include <pthread.h>
pthread_t pthread_self(void);

Vidíme tedy, že funkci ‚pthread_self()‘ používá vlákno pro tisk vlastního ID vlákna.

Nyní bychom se zeptali na případ, kdy by byly vyžadovány výše uvedené dvě funkce. Předpokládejme, že existuje případ, kdy seznam odkazů obsahuje data pro různá vlákna. Každý uzel v seznamu obsahuje ID vlákna a odpovídající data. Nyní, kdykoli se vlákno pokusí načíst svá data z propojeného seznamu, nejprve získá své vlastní ID voláním 'pthread_self()' a poté zavolá 'pthread_equal()' na každém uzlu, aby zjistilo, zda uzel obsahuje data pro něj nebo ne. .

Příkladem výše uvedeného obecného případu je případ, kdy hlavní vlákno získá úlohy ke zpracování a poté je vloží do seznamu odkazů. Nyní jednotlivá pracovní vlákna analyzují propojený seznam a extrahují úlohu, která jim byla přiřazena.

Vytvoření vlákna

Normálně, když se program spustí a stane se procesem, spustí se s výchozím vláknem. Můžeme tedy říci, že každý proces má alespoň jedno vlákno řízení. Proces může vytvořit další vlákna pomocí následující funkce:

#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void), void *restrict arg)

Výše uvedená funkce vyžaduje čtyři argumenty, nejprve o nich trochu pohovořme:

  • Prvním argumentem je adresa typu pthread_t. Jakmile je funkce úspěšně volána, proměnná, jejíž adresa je předána jako první argument, bude obsahovat ID vlákna nově vytvořeného vlákna.
  • Druhý argument může obsahovat určité atributy, které chceme, aby nové vlákno obsahovalo. Může to být priorita atd.
  • Třetím argumentem je ukazatel funkce. To je něco, co je třeba mít na paměti, že každé vlákno začíná funkcí a že adresa funkcí je zde předána jako třetí argument, aby jádro vědělo, ze které funkce má vlákno spustit.
  • Vzhledem k tomu, že funkce (jejíž adresa je předána ve třetím argumentu výše) může také přijmout některé argumenty, takže tyto argumenty můžeme předat ve formě ukazatele na typ void. Proč byl vybrán typ prázdnoty? Bylo to proto, že pokud funkce přijímá více než jeden argument, pak tento ukazatel může být ukazatelem na strukturu, která může tyto argumenty obsahovat.

Příklad praktického vlákna

Následuje příklad kódu, kde jsme se pokusili použít všechny tři výše popsané funkce.

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>

pthread_t tid[2];

void* doSomeThing(void *arg)
{
    unsigned long i = 0;
    pthread_t id = pthread_self();

    if(pthread_equal(id,tid[0]))
    {
        printf("\n First thread processing\n");
    }
    else
    {
        printf("\n Second thread processing\n");
    }

    for(i=0; i<(0xFFFFFFFF);i++);

    return NULL;
}

int main(void)
{
    int i = 0;
    int err;

    while(i < 2)
    {
        err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
        if (err != 0)
            printf("\ncan't create thread :[%s]", strerror(err));
        else
            printf("\n Thread created successfully\n");

        i++;
    }

    sleep(5);
    return 0;
}

Tento kód tedy dělá:

  • Používá funkci pthread_create() k vytvoření dvou vláken
  • Spouštěcí funkce pro obě vlákna zůstává stejná.
  • Uvnitř funkce ‘doSomeThing()’ vlákno používá funkce pthread_self() a pthread_equal() k identifikaci, zda je spouštěné vlákno první nebo druhé, jak bylo vytvořeno.
  • Uvnitř stejné funkce „doSomeThing()“ je také spuštěn cyklus for, který simuluje časově náročnou práci.

Nyní, když je výše uvedený kód spuštěn, byl výstup následující:

$ ./threads
Thread created successfully
First thread processing
Thread created successfully
Second thread processing

Jak je vidět na výstupu, první vlákno je vytvořeno a začne zpracovávat, poté je vytvořeno druhé vlákno a poté začne zpracování. Zde je třeba poznamenat, že pořadí provádění vláken není vždy pevně dané. Záleží na plánovacím algoritmu OS.

Poznámka:Celé vysvětlení v tomto článku je provedeno ve vláknech Posix. Jak lze z typu pochopit, typ pthread_t znamená vlákna POSIX. Pokud chce aplikace otestovat, zda jsou vlákna POSIX podporována nebo ne, může aplikace použít makro _POSIX_THREADS pro test doby kompilace. Chcete-li zkompilovat kód obsahující volání rozhraní API posix, použijte možnost kompilace ‚-pthread‘.


Linux
  1. Jak vytvořit soubor s danou velikostí v Linuxu?

  2. Jak pojmenovat vlákno v Linuxu?

  3. Jak vytvoříte okno v Linuxu s C++?

  1. Jak vytvořit uživatele s vlastním domovským adresářem v Linuxu

  2. Jak získat ID vlákna pthread v programu linux c?

  3. Jak vytvořit příklad linuxového potrubí v c

  1. Jak vytvořit soubory Linux Proc v programu C pomocí LKM

  2. Jak ukončit vlákno v programu C ( příklad pthread_exit )

  3. Jak vytvořit systém souborů ZFS pomocí komprese souborů v systému Linux