plik


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śin
SO 05 Watki
watki
watki
opis watki (2)
Wątki mitologiczne w sztuce nowożytnej
opis watki
watki
Java watki
sołtys,systemy operacyjne, wątki
wyk watki mutexy
wątki
Wątki
Wątki
watki

więcej podobnych podstron