Obsługa wątkówLaboratorium QNXPoprzedniRozdział 4. Wątki i mechanizmy synchronizacji wątkówNastępny4.2. Obsługa wątkówObsługa wątków w systemie QNX jest realizowana przez mikrojądro QNX Neutrino.
System QNX dostarcza standardowego interfejsu wątków POSIX (pthreads),
zdefiniowanego w standardzie POSIX 1003.1. QNX zapewnia wszystkie procedury
obsługi i synchronizacji wątków. Poniżej krótkie omówienie sposobu obsługi
wątków oraz przykłady korzystania z API wątków POSIX'owych. W programach korzystających z wątków POSIX należy dołączać plik nagłówkowy
pthread.h:
#include <pthread.h>
...
Przy kompilacji (dokładniej przy konsolidacji) należy dołączyć bibliotekę
libc. Przykładowo, żeby skompilować program a.c
należy wpisać:
$ qcc a.c -l c
Wszystkie funkcje oraz typy danych tworzące API wątków POSIX'owych mają nazwy
rozpoczynające się od przedrostka pthread_.4.2.1. Prosty scenariuszNajprostszy scenariusz, wg którego można realizować pracę programu
wielowątkowego jest następujący
Utworzenie dodatkowych wątków. Tutaj wskazuje się również procedury,
które mają być wykonane w ramach wątków Wykonanie procedur "wątkowych". Po wykonaniu procedury
pojedynczy wątek kończy działanie.Wątek główny przed zakończeniem działania oczekuje na zakończenie
wszystkich utworzonych wątków (dołączenie wątków - join). Zaniedbanie tego
może spowodować, że dodatkowe wątki nie zdążą zrealizować zadania zanim
zakończy się działanie wątku głównego (wątki zginą w chwili zakończenia
wątku głównego)Prosty scenariusz pracy wielowątkowej4.2.2. Identyfikator wątkuKażdy wątek w systemie posiada swój unikalny identyfikator. Standard POSIX
definiuje specjalny typ danych pthread_t do reprezentacji
identyfikatora wątku. Przy pomocy identyfikatora można wskazać na dowolny wątek
w systemie.Do pobrania identyfikatora wątku można użyć procedury
pthread_self(). Możliwe jest również porównywanie dwu
identyfikatorów funkcją pthread_equal().Przykład 4-1. Pobranie identyfikatora wątkuPoniższy program wyświetla identyfikator wątku. Skompilować i uruchomić. #include <stdio.h>
#include <pthread.h>
int main(int argc, char * argv[])
{
pthread_t id;
id = pthread_self();
printf("%ld\n",(long int)id);
return 0;
}4.2.3. Tworzenie wątkuWątek można stworzyć wywołując funkcję pthread_create()Przykład 4-2. Tworzenie wątkuPoniższy program tworzy oddzielny wątek. Każdy wątek wyświetla swój
identyfikator. Skompilować i uruchomić. #include <stdio.h>
#include <pthread.h>
/* Procedura wykonywana przez watek */
void* start(void* arg)
{
pthread_t id;
id = pthread_self();
printf("Start: %ld\n",(long int)id);
return NULL;
}
int main(int argc, char* argv[])
{
pthread_t id; /* Identyfikator tego watku*/
pthread_t start_id; /* identyfikator tworzonego watku */
pthread_attr_t attr; /* Atrybuty watku */
/* Inicjalizuj strukture z atrybutami*/
pthread_attr_init( &attr );
/* Utworz nowy watek. "start" tutaj to nazwa procedury,
ktora bedzie watkiem (patrz funkcja start() na poczatku). */
pthread_create(&start_id, &attr, start, NULL);
/* Wyswietl identyfikator */
id = pthread_self();
printf("Main: %ld\n",(long int)id);
/* Czekaj na zakonczenie watku "start" */
pthread_join(start_id, NULL);
return 0;
}W chwili tworzenia wątku, można również przekazać do niego dodatkowe dane. Dane
te są "dostarczane" do procedury wątkowej poprzez argument
arg.Przykład 4-3. Przekazywanie argumentu do wątkuZmodyfikuj poprzedni program tak, aby do procedury start()
przekazać identyfikator wątku głównego. Oba identyfikatory powinna wyświetlać
teraz funkcja start(). #include <stdio.h>
#include <pthread.h>
/* Procedura wykonywana przez watek */
void* start(void* arg)
{
pthread_t id;
pthread_t main_id;
id = pthread_self();
main_id = (pthread_t)arg;
printf("Start: %ld\n",(long int)id);
printf("Main: %ld\n",(long int)main_id);
return NULL;
}
int main(int argc, char* argv[])
{
pthread_t id; /* Identyfikator tego watku*/
pthread_t start_id; /* identyfikator tworzonego watku */
pthread_attr_t attr; /* Atrybuty watku */
/* Inicjalizuj strukture z atrybutami*/
pthread_attr_init( &attr );
/* Wyswietl identyfikator */
id = pthread_self();
/* Utworz nowy watek i przekaz 'id' jako argument */
pthread_create(&start_id, &attr, start, (void*)id);
/* Czekaj na zakonczenie watku "start" */
pthread_join(start_id, NULL);
return 0;
}4.2.4. Kończenie wątkuW poprzednich przykładach wątek start kończył działanie po
napotkaniu instrukcji return NULL; void* start(void* arg)
{
...
return NULL; /* Tu się skończy wątek */
}Alternatywnie, można zakończyć wątek wywołując funkcję
pthread_exit() void* start(void* arg)
{
...
pthread_exit(NULL); /* Tu się skończy wątek */
...
}4.2.5. Dołączanie wątku (join)Dołączanie przeprowadza się funkcją pthread_join().
Wywołanie:
pthread_join(id,&retval)
powoduje wstrzymanie programu aż do momentu zakończenia wątku
id.4.2.6. Odłączanie wątku (detach)Wątek można odłączyć. W normalnej sytuacji po zakończeniu wątku pewne jego
zasoby są wciąż przechowywane aż do momentu dołączenia wątku funkcją
pthread_join(). Wątek odłączony zwalnia swoje zasoby zaraz
po zakończeniu pracy. Nie ma potrzeby (ani możliwości) oczekiwania (join) na
odłączony wątek. Wszelka informacja związana z wątkiem znika w chwili
zakończenia jego pracy.Wątek odłącza się funkcją pthread_detach():
...
pthread_detach(id);
...4.2.7. Współbieżna praca wątkówPrzykład 4-4. Współbieżna praca wątkówPoniższy przykład demonstruje współbieżną pracę dwu wątków. Jest on modyfikacją
pierwszego programu dot. wątków. Wątek główny oraz dodatkowy wątek
start drukują niezależnie w pętli swoje identyfikatory.
Należy zauważyć, obie pętle wykonywane są równocześnie (współbieżnie). Napisy z
wątku głównego i dodatkowego pojawiają się na przemian. Skompilować i uruchomić
program. #include <stdio.h>
#include <pthread.h>
#include <unistd.h>
/* Procedura wykonywana przez watek */
void* start(void* arg)
{
int i;
pthread_t id;
id = pthread_self();
for( i=0; i<10; i++)
{
printf("\t\t\tStart: %ld\n",(long int)id);
sleep(1);
}
return NULL;
}
int main(int argc, char* argv[])
{
int i; /* Zmienna licznikowa dla petli */
pthread_t id; /* Identyfikator tego watku*/
pthread_t start_id; /* identyfikator tworzonego watku */
pthread_attr_t attr; /* Atrybuty watku */
/* Inicjalizuj strukture z atrybutami*/
pthread_attr_init( &attr );
/* Utworz nowy watek (nazwijmy go "start") */
pthread_create(&start_id, &attr, start, NULL);
id = pthread_self();
for( i=0; i<5; i++)
{
/* Wyswietl identyfikator */
printf("Main: %ld\n",(long int)id);
sleep(2);
}
/* Czekaj na zakonczenie watku "start" */
pthread_join(start_id, NULL);
return 0;
}PoprzedniSpis treściNastępnyWątki i mechanizmy synchronizacji wątkówPoczątek rozdziałuMechanizmy synchronizacji wątków
Wyszukiwarka
Podobne podstrony:
wÄ
tki ceglane pĹinSO 05 Watkiwatkiwatkiopis watki (2)WÄ
tki mitologiczne w sztuce nowoĹźytnejopis watkiwatkiJava watkisoĹtys,systemy operacyjne, wÄ
tkiwyk watki mutexywÄ
tkiWÄ
tkiWÄ
tkiwatkiwiÄcej podobnych podstron