POSIX Threads/Wstęp
Podstawowe informacje o bibliotece
edytujSpecyfikacja POSIX jest dostępna nieodpłatnie na stronie organizacji Open Group (http://www.opengroup.org/). Dla wygody Czytelnika linkujemy w tym podręczniku do konkretnych podstron opisujących funkcje.
Opis części implementacji dla systemu Linux znajduje się na stronie The Linux man-pages project (http://www.kernel.org/doc/man-pages/).
Niektóre strony podręczników zawierają przykładowe programy. |
Pliki nagłówkowe
edytujPodstawowy plik nagłówkowy biblioteki POSIX Threads nazywa się pthread.h i jego włączenie do programu jest konieczne. Dokładny wykaz funkcji znajdujących się w tym pliku, wraz z adnotacjami opcji, znajduje się na stronie http://www.opengroup.org/onlinepubs/009695399/basedefs/pthread.h.html.
Oprócz niego:
- sys/types.h - typy danych (domyślnie włączane przez pthread.h)
- limits.h - stałe określające ograniczenia biblioteki
Konwencje nazewnicze
edytujNazwy funkcji i typów zaczynają się zawsze od pthread_, stałe są pisane wielkimi literami i podobnie rozpoczynają od PTHREAD_. Nazewnictwo poza tym jest bardzo konsekwentne, podobnie kolejność argumentów itd.
Typy danych
edytujTypy definiowane przez bibliotekę powinny być traktowane jako abstrakcyjne - jedynym sposobem ich inicjalizacji, zmiany wartości, itd. jest użycie dedykowanych funkcji.
Uwaga!
|
Nazwy funkcji tworzących obiekty są zgodne ze schematem pthread_XXX_init, natomiast niszczące obiekt pthread_XXX_destroy.
Atrybuty
edytujWszelkie dodatkowe parametry obiektów tworzonych w bibliotece są opisywane atrybutami, tj. innymi obiektami, które przechowują określone parametry. Obiekty atrybutów mogą być używane wielokrotnie do tworzenia różnych obiektów.
Zgłaszanie błędów
edytujWiększość funkcji z pthreads zwraca wartości typu int, która określa status operacji. Jeśli jest równy zero, funkcja wykonała się poprawnie, w przeciwnym razie zwracana jest standardowa wartość błędu (w rodzaju EINVAL, ENOMEM, EBUSY).
Można więc używać funkcji strerror (doc), ewentualnie przypisywać wynik do zmiennej errno i korzystać z funkcji perror (doc). Standard POSIX określa, że errno w środowisku wielowątkowym jest lokalne względem wątku.
Na przykład:
#include <string.h>
#include <errno.h>
int main() {
int status;
status = pthread_XXX(...);
if (status)
printf("Błąd przy wywoływaniu pthread_XXX: %s", strerror(status));
errno = pthread_XXX(...);
if (errno)
perror("pthread_XXX");
return 0;
}
Dane użytkownika
edytujWszystkie dane użytkownika są przekazywane przez wskaźniki typu void*. O interpretacji wskaźników i danych na które wskazują decyduje wyłącznie programista, biblioteka pthreads nie określa ani nie ogranicza tego w żaden sposób.
Kompilacja
edytujPonieważ pthreads jest zewnętrzną biblioteką należy linkerowi podać ścieżkę do pliku bibliotecznego. Np. przy kompilacji gcc należy dodać opcję -lpthread.
Opcje standardu
edytujImplementacja biblioteki pthreads nie musi dostarczać wszystkich funkcji opisanych w standardzie, dopuszcza on szereg opcjonalnych rozszerzeń. W tym podręczniku posługujemy się skrótami używanymi na stronach Open Group:
- rozszerzenia (XSI)
- zmiana/odczyt rozmiaru zabezpieczającego stosu
- wybór typu mutexu
- zmiana/odczyt stopnia współbieżności
- bariery (BAR)
- wirujące blokady (SPI)
- zmiana priorytetu wątku posiadającego blokadę (TPP - Thread Priority Protection, TPI - Thread Priority Inheritance)
- szeregowanie wątków (TPS - Thread Execution Scheduling)
- synchronizacja między wątkami różnych procesów (TSH - Thread Process-Shared Synchronization)
- dodatkowy algorytm szeregowania dla zadań aperiodycznych w systemach czasu rzeczywistego (TPS - Thread Sporadic Server)
- Rozmiar i adres stosu (TSS - Thread Stack Size Attribute)
- Rozmiar i adres stosu (TSA - Thread Stack Address Attribute)
- możliwość wyboru zegara odmierzającego czas przy oczekiwaniu na zmienną warunkową; domyślnie używany jest zegar systemowy (CS - Clock Selection)
- czas procesora zużyty przez wątek (TCT - Thread CPU-Time Clocks)
- możliwość ograniczonego czasowo oczekiwania na uzyskanie blokad (mutexy) oraz blokad do odczytu/zapisu (TMO - Timeouts)
C++
edytujUżycie biblioteki pthreads w programach pisanych w języku C++ jest oczywiście możliwe. Należy jedynie w procedurach wykonywanych w wątkach (patrz Tworzenie wątku) obsługiwać wszystkie wyjątki:
void* wątek(void* arg) {
try {
// ...
// treść wątku
// ...
}
catch (wyjątek1) {
// obsługa wyjątku 1
}
catch (wyjątek2) {
// obsługa wyjątku 2
}
catch (...) {
// wszystkie pozostałe wyjątki
}
}
Uwaga! Przerywanie wątków w implementacji NPTL jest realizowane poprzez zgłoszenie wyjątku - jeśli w wątku zostanie użyte catch (...), wówczas program zakończy się komunikatem FATAL: exception not rethrown. Urlich Drepper wyjaśnia na swoim blogu, jak obejść ten problem.
O podręczniku
edytujPrzykłady
edytujPrzykładowe programy mają jedynie na celu zilustrowanie pewnych cech biblioteki. Jednocześnie są to w pełni funkcjonalne programy - każdy może je skopiować do swojego komputera, skompilować i uruchomić. Mają być ułatwieniem dla własnych eksperymentów lub testów.