Celem ćwiczenia było zapoznanie się z biblioteką pthread udostępnianą przez standard POSIX. Należało zapoznać się z tworzeniem, niszczeniem i elementarną synchronizacją wątków. Żeby to było możliwe musieliśmy poznać obiekty określające atrybuty wątków.
Biblioteka pthreads jest mechanizmem zarządzania wątkami rozpowszechnionym wśród różnych dystrybucji systemów z rodziny Unix. Jest ona dostępna dla języka C. Dzięki jednolitym interfejsom zyskujemy przenośność programów napisanych z użyciem wielowątkowości, czego nie dawały nam funkcje systemowe clone i fork. W praktyce pthread w większości przypadków wykorzystuje funkcję clone jednak będąc w wyższej warstwie daje większą swobodę i łatwość tworzenia oprogramowania.
Aby móc wykonać ćwiczenie musieliśmy zapoznać się z kilkoma funkcjami, które udostępnia nam wspomniana biblioteka:
int pthread_create(pthread_t*, const pthread_attr_t*, void*(*function) (void*), void*);
Funkcja ta tworzy nam nowy wątek. Jako pierwszy argument przyjmuje nam adres zmiennej typu pthread, do którego jest zapisywany identyfikator wątku. Dzięki temu możemy się odwołać do konkretnego wątku w procesie, w którym jest on tworzony. Kolejny argument jest to struktura, w której możemy ustalić atrybuty naszego wątku. Ostatnie dwa argumenty to wskaźnik na funkcję, którą ten wątek wykona oraz argument jaki chcemy tej funkcji przekazać. Funkcja pthread_create zwraca zero w przypadku udanego tworzenia wątku. W innym przypadku zwraca kod błędu.
pthread_cancel(pthread_t) – wysyła sygnał zabicia wątku.
pthread_join(pthread_t, void*) – oczekuje na zakończenie wątku i odbiera zwracane dane.
pthread_detach(pthread_t) – odczepia wątek.
pthread_attr_init(pthread_attr_t*) – inicjuje atrybuty wartościami domyślnymi.
pthread_attr_setdetachstate(pthread_attr_t*, int) – pozwala ustalić, czy wątek będzie na starcie odczepiony czy nie.
Nasze zadanie polegało na uzupełnieniu odpowiednimi procedurami kodu udostępnionego przez prowadzącego zgodnie z poleceniami w komentarzach. Program tworzył trzy wątki. Każdy z nich wykonywał funkcję, która uniemożliwiała odczepienie wątku na pewien czas. Dwa z nich były z atrybutami domyślnymi oraz jeden ustawiony jako wątek odczepiony od samego startu. Prześledziliśmy działanie wątku z atrybutami domyślnymi, następnie takiego samego wątku, lecz odczepiliśmy go zaraz po starcie. Ostatni wątek był odczepiony od samego początku.
Jako zadanie dodatkowe, wykonałem również prosty program, który tworzy dziesięć wątków z losowymi parametrami. Na podstawie ich działania określał czy są odczepione o czym informował krótkim zdaniem wypisanym na ekran.
Na tych zajęciach poznaliśmy mechanizm odczepiania wątku. Odczepiając wątek, dajemy sygnał systemowi, że po zakończeniu pracy może zając jego zasoby pamięci. Powinniśmy odczepiać każdy wątek, który nie ma na celu zwrócenia nam jakiś danych. Wątki określane jako przyczepione blokują zasoby, oczekując na ich odebranie. Nauczyliśmy się też jak możemy zablokować możliwość odczepienia wątku oraz jak ją ponownie włączyć. Ważnym elementem było też wykorzystanie zmiennej globalnej, dzięki której mogliśmy określić czy wątek się wykonał mimo że go odczepiliśmy.
Kody źródłowe:
Zadanie podstawowe: http://wklej.to/1HR1V
Zadanie dodatkowe: http://wklej.to/eXDSx