Läsare som du hjälper till att stödja MUO. När du gör ett köp med hjälp av länkar på vår webbplats kan vi tjäna en affiliate-provision. Läs mer.

På Linux kan du skapa och hantera trådar i C/C++ med hjälp av POSIX-trådsbiblioteket (pthread). Till skillnad från andra operativsystem är det liten skillnad mellan en tråd och en process i Linux. Det är därför Linux ofta refererar till sina trådar som lätta processer.

Med hjälp av pthread-biblioteket kan du skapa trådar, vänta på att de ska avslutas och avsluta dem explicit.

Historien om trådanvändning på Linux

Före Linux version 2.6 var huvudtrådsimplementeringen LinuxThreads. Denna implementering hade betydande begränsningar vad gäller prestanda och synkroniseringsoperationer. En gräns för det maximala antalet trådar som kunde köras begränsade dem till på 1000-talet.

2003 lyckades ett team ledd av utvecklare från IBM och RedHat göra Inbyggt POSIX-trådbibliotek (NPTL) projekt tillgängligt. Den introducerades först i RedHat Enterprise version 3 för att lösa prestandaproblem med Java Virtual Machine på Linux. Idag innehåller GNU C-biblioteket implementeringar av båda trådningsmekanismerna.

instagram viewer

Ingen av dessa är en implementering av gröna trådar, som en virtuell maskin skulle hantera och köra i rent användarläge. När du använder pthread-biblioteket skapar kärnan en tråd varje gång ett program startar.

Du kan hitta trådspecifik information för alla pågående processer i filerna under /proc//task. Detta är standardplatsen för processinformation under procfs Linux-standard. För entrådiga applikationer kommer det att verka som att det finns en uppgiftspost med samma värde som PID under denna katalog.

Trådarnas arbetslogik

Trådar är som processer som för närvarande körs på operativsystemet. I system med en processor (t.ex. mikrokontroller) simulerar operativsystemets kärna trådar. Detta gör att transaktioner kan köras samtidigt genom slicing.

Ett operativsystem med en kärna kan egentligen bara köra en process åt gången. Dock i multi-core eller multi-processor system, kan dessa processer köras samtidigt.

Trådskapande i C

Du kan använda pthread_create funktion för att skapa en ny tråd. De pthread.h header-filen innehåller sin signaturdefinition tillsammans med andra trådrelaterade funktioner. Trådar använder samma adressutrymme och filbeskrivningar som huvudprogrammet.

Pthread-biblioteket inkluderar också det nödvändiga stödet för mutex och villkorsoperationer som krävs för synkroniseringsoperationer.

När du använder funktionerna i pthread-biblioteket måste du se till att kompilatorn länkar pthread bibliotek till din körbara fil. Om det behövs kan du instruera kompilatorn att länka till biblioteket med hjälp av -l alternativ:

gcc -o testa test_thread.c -lpthread

Funktionen pthread_create har följande signatur:

intpthread_create(pthread_t *tråd, konstpthread_attr_t *attr, tomhet *(*start_rutin)(tomhet *), tomhet *arg)

Den returnerar 0 om proceduren lyckas. Om det finns ett problem returnerar den en felkod som inte är noll. I ovanstående funktionssignatur:

  • De tråd parametern är av typ pthread_t. Den skapade tråden kommer alltid att vara tillgänglig med denna referens.
  • De attr parameter låter dig ange anpassat beteende. Du kan använda en serie trådspecifika funktioner som börjar med pthread_attr_ för att ställa in detta värde. Möjliga anpassningar är schemaläggningspolicyn, stackstorleken och frikopplande policy.
  • start_rutin anger funktionen som tråden ska köras.
  • arg representerar en generisk datastruktur som skickas till funktionen av tråden.

Här är ett exempel på en applikation:

#omfatta
#omfatta
#omfatta
#omfatta

tomhet *arbetstagare(tomhet *data)
{
röding *namn = (röding*)data;

för (int jag = 0; jag < 120; i++)
{
du sover(50000);
printf("Hej från trådnamn = %s\n", namn);
}

printf("Tråden %s klar!\n", namn);
lämna tillbakaNULL;
}

inthuvud(tomhet)
{
pthread_t th1, th2;
pthread_create(&th1, NULL, arbetare, "X");
pthread_create(&th2, NULL, arbetare, "Y");
sova(5);
printf("Avsluta huvudprogrammet\n");
lämna tillbaka0;
}

Trådtyper

När en tråd kommer tillbaka från main() funktion i en applikation avslutas alla trådar och systemet frigör alla resurser som programmet använt. Likaså när du avslutar en tråd med ett kommando som en utgång(), kommer ditt program att avsluta alla trådar.

Med pthread_join funktion kan du vänta tills en tråd avslutas istället. Tråden som använder denna funktion kommer att blockeras tills den förväntade tråden avslutas. Resurserna som de använder från systemet returneras inte ens i fall som avslutning av sammanfogningsbara trådar, oplanerade av CPU: n eller till och med misslyckas med att ansluta med ptread_join.

Ibland finns det situationer där det inte är meningsfullt att gå med pthread_join; om det är omöjligt att förutsäga när tråden slutar, till exempel. I det här fallet kan du se till att systemet returnerar alla resurser automatiskt vid den punkt där tråden returnerar.

För att uppnå detta bör du starta relevanta trådar med FRILIGGANDE status. När du startar en tråd, LÖSGÖRA status kan ställas in via en tråd attributvärden eller med pthread_detach fungera:

intpthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
intpthread_detach(pthread_t tråd);

Här är ett exempel på användning av pthread_join(). Byt ut huvudfunktionen i det första programmet med följande:

inthuvud(tomhet)
{
pthread_t th1, th2;
pthread_create(&th1, NULL, arbetare, "X");
pthread_create(&th2, NULL, arbetare, "Y");
sova(5);
printf("avslutar huvudprogrammet\n");
pthread_join (th1, NULL);
pthread_join (th2, NULL);
lämna tillbaka0;
}

När du kompilerar och kör programmet blir din utdata:

Hej från tråd Y
Hej från tråd X
Hej från tråd Y
...
Hej från tråd Y
avslutar huvudprogrammet
Hej från tråd X
...
Hej från tråd X
Tråd X klar!
Hej från tråd Y
Tråd Y klar!

Trådavslutning

Du kan avbryta en tråd med ett anrop till pthread_cancel, skicka motsvarande pthread_t id:

intpthread_cancel(pthread_t tråd);

Du kan se detta i aktion i följande kod. Återigen, bara huvud funktionen är annorlunda:

inthuvud(tomhet)
{
pthread_t th1, th2;
pthread_create(&th1, NULL, arbetare, "X");
pthread_create(&th2, NULL, arbetare, "Y");
sova(1);
printf("> Avbryter tråd Y!!\n");
pthread_cancel (th2);
du sover(100000);
printf("> Avbryter tråd X!\n");
pthread_cancel (th1);
printf("avslutar huvudprogrammet\n");
lämna tillbaka0;
}

Varför skapas trådar?

Operativsystem försöker alltid köra trådar på en eller flera processorer, antingen från en självskapad lista eller från en användarskapad trådlista. Vissa trådar kan inte köras eftersom de väntar på en in-/utsignal från hårdvaran. De kan också vänta frivilligt, vänta på svar från en annan tråd, eller ha en annan tråd som blockerar dem.

Du kan justera resurserna du allokerar till trådar som du skapar med pthread. Detta kan vara en anpassad schemaläggningspolicy, eller så kan du välja schemaläggningsalgoritmer som FIFO eller Round-robin om så önskas.