Linuxon a POSIX szál (pthread) könyvtár használatával C/C++ nyelven hozhat létre és kezelhet szálakat. Más operációs rendszerekkel ellentétben a Linuxban alig van különbség a szál és a folyamat között. Ez az oka annak, hogy a Linux gyakran könnyű folyamatként hivatkozik a szálaira.
A pthread könyvtár segítségével létrehozhat szálakat, megvárhatja, amíg véget érnek, és kifejezetten leállíthatja őket.
A szálhasználat története Linuxon
A Linux 2.6-os verziója előtt a fő szál megvalósítása a LinuxThreads volt. Ennek a megvalósításnak jelentős korlátai voltak a teljesítmény és a szinkronizálási műveletek tekintetében. A futtatható szálak maximális számának korlátozása az 1000-es évekre korlátozta őket.
2003-ban az IBM és a RedHat fejlesztői által vezetett csapatnak sikerült elkészítenie a Natív POSIX szálkönyvtár (NPTL) projekt elérhető. Először a RedHat Enterprise 3-as verziójában vezették be, hogy megoldja a Linuxon futó Java virtuális gép teljesítményével kapcsolatos problémákat. Ma a GNU C könyvtár mindkét szálfűzési mechanizmus megvalósítását tartalmazza.
Ezek egyike sem zöld szálak megvalósítása, amelyeket egy virtuális gép kezelne és tisztán felhasználói módban futtatna. A pthread könyvtár használatakor a kernel minden egyes program indításakor létrehoz egy szálat.
Az alábbi fájlokban találhat szálspecifikus információkat bármely futó folyamatról /proc/
A szálak működési logikája
A szálak olyanok, mint az operációs rendszeren jelenleg futó folyamatok. Egyprocesszoros rendszerekben (pl. mikrokontrollerek) az operációs rendszer kernelje szimulálja a szálakat. Ez lehetővé teszi a tranzakciók egyidejű futtatását a szeleteléssel.
Egy egymagos operációs rendszer valóban csak egy folyamatot tud egyszerre futtatni. Azonban in többmagos vagy többprocesszoros rendszerek, ezek a folyamatok egyidejűleg is futhatnak.
Szál létrehozása C-ben
Használhatja a pthread_create függvényt új szál létrehozásához. A pthread.h fejléc fájl tartalmazza az aláírás definícióját, valamint a többi szálhoz kapcsolódó függvényt. A szálak ugyanazt a címteret és fájlleírókat használják, mint a fő program.
A pthread könyvtár tartalmazza a szinkronizálási műveletekhez szükséges mutex és feltételes műveletek szükséges támogatását is.
Amikor a pthread könyvtár funkcióit használja, gondoskodnia kell arról, hogy a fordító csatolja a pszál könyvtárat a végrehajtható fájlba. Ha szükséges, utasíthatja a fordítót, hogy hivatkozzon a könyvtárra a -l választási lehetőség:
gcc -o teszt teszt_szál.c -lpthread
A pthread_create függvény a következő aláírással rendelkezik:
intpthread_create(pthread_t *cérna, constpthread_attr_t *attr, üres **(*start_rutin)(üres *), üres *arg)
0 értéket ad vissza, ha az eljárás sikeres. Ha probléma van, nullától eltérő hibakódot ad vissza. A fenti függvény aláírásában:
- A cérna paraméter típusú pthread_t. A létrehozott szál mindig elérhető lesz ezzel a hivatkozással.
- A attr paraméter lehetővé teszi az egyéni viselkedés megadását. Egy sor szál-specifikus függvényt használhat, kezdve a pthread_attr_ ennek az értéknek a beállításához. A lehetséges testreszabások az ütemezési házirend, a verem mérete és a leválasztási szabályzat.
- start_rutin megadja a függvényt, amelyet a szál futtatni fog.
- arg a szál által a függvénynek átadott általános adatszerkezetet képvisel.
Íme egy példa alkalmazás:
#tartalmazza
#tartalmazza
#tartalmazza
#tartalmazzaüres *munkás(üres *adat)
{
char *név = (char*)adat;
számára (int i = 0; én < 120; én++)
{
alszol(50000);
printf("Szia a szál nevétől = %s\n", név);
}
printf("%s szál kész!\n", név);
VisszatérésNULLA;
}
intfő-(üres)
{
pthread_t th1, th2;
pthread_create(&th1, NULLA, dolgozó, "X");
pthread_create(&th2, NULLA, dolgozó, "Y");
alvás(5);
printf("Kilépés a főprogramból\n");
Visszatérés0;
}
Száltípusok
Amikor egy szál visszatér a fő() funkció egy alkalmazásban, minden szál leáll, és a rendszer felszabadítja a program által használt összes erőforrást. Hasonlóképpen, amikor egy szálból kilép egy paranccsal, például an kijárat(), a program minden szálat leállít.
A... val pthread_join függvényt, megvárhatja, amíg egy szál véget ér. Az ezt a funkciót használó szál addig blokkol, amíg a várt szál véget nem ér. Az általuk használt erőforrások a rendszerből még olyan esetekben sem térnek vissza, mint például az összekapcsolható szálak megszakadása, a CPU által nem ütemezett, vagy akár a csatlakozás sikertelensége ptread_join.
Néha vannak olyan helyzetek, amikor a pthread_join paranccsal való csatlakozásnak nincs értelme; ha például lehetetlen megjósolni, hogy mikor ér véget a szál. Ebben az esetben biztosíthatja, hogy a rendszer automatikusan visszaadja az összes erőforrást azon a ponton, ahol a szál visszatér.
Ennek eléréséhez a megfelelő szálakat a KÜLÖNÁLLÓ állapot. Egy szál indításakor LESZÁLLÍTÁS állapota beállítható egy szál attribútumértékekkel vagy a pthread_detach funkció:
intpthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
intpthread_detach(pthread_t cérna);
Íme egy példa a pthread_join() használatára. Cserélje le a fő funkciót az első programban a következőre:
intfő-(üres)
{
pthread_t th1, th2;
pthread_create(&th1, NULLA, dolgozó, "X");
pthread_create(&th2, NULLA, dolgozó, "Y");
alvás(5);
printf("kilépés a főprogramból\n");
pthread_join (th1, NULLA);
pthread_join (th2, NULLA);
Visszatérés0;
}
Amikor lefordítja és futtatja a programot, a kimenet a következő lesz:
Üdvözlet az Y szálból
Üdvözlet az X szálból
Üdvözlet az Y szálból
...
Üdvözlet az Y szálból
kilépés a főprogramból
Üdvözlet az X szálból
...
Üdvözlet az X szálból
Kész az X szál!
Üdvözlet az Y szálból
Y szál kész!
Szálmegszakítás
A szálat a pthread_cancel hívásával szakíthatja meg, átadva a megfelelőt pthread_t azonosító:
intpthread_cancel(pthread_t cérna);
Ezt működés közben láthatja a következő kódban. Ismét csak a fő- a funkció más:
intfő-(üres)
{
pthread_t th1, th2;
pthread_create(&th1, NULLA, dolgozó, "X");
pthread_create(&th2, NULLA, dolgozó, "Y");
alvás(1);
printf("> Y szál megszakítása!!\n");
pthread_cancel (th2);
alszol(100000);
printf("> X szál megszakítása!\n");
pthread_cancel (th1);
printf("kilépés a főprogramból\n");
Visszatérés0;
}
Miért jönnek létre szálak?
Az operációs rendszerek mindig megpróbálnak szálakat futtatni egy vagy több CPU-n, akár egy saját készítésű listából, akár egy felhasználó által létrehozott szállistából. Egyes szálak nem futhatnak, mert a hardver bemeneti/kimeneti jelére várnak. Előfordulhat, hogy önként várnak, egy másik száltól várnak választ, vagy egy másik szál blokkolja őket.
Beállíthatja a pthread használatával létrehozott szálakhoz lefoglalt erőforrásokat. Ez lehet egyéni ütemezési házirend, vagy választhat ütemezési algoritmusokat, például FIFO-t vagy Round-robint, ha kívánja.