2010-11-17 10 views
10

Wiem, jak wysyłać sygnały do ​​procesu potomnego w C, używając funkcji kill(pid_t pid, int sig). A co z wysyłaniem sygnałów do wątków? Czy to możliwe?. Jeśli tak, to jak przechwytywać sygnały w wątku "potomnym". Na przykład, jeśli główny wątek wysyła mi sygnał zakończenia, jak mogę go w innym wątku złapać.Wysyłaj i przejmuj sygnały do ​​pthreadów w C

Odpowiedz

8

Z wątkami POSIX, masz funkcje pthread_cond_wait i pthread_cond_signal.

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex) 
int pthread_cond_signal(pthread_cond_t *cond) 

sygnalizowanym gwint powinny blokować na pthread_cond_wait rozmowy, dopóki inna nić wysyła sygnał przez pthread_cond_signal, o tej samej wielkości stanu.

Biorąc pod uwagę analogię z sygnałami dostarczanymi do procesów, jest to nieco inne, ponieważ sygnalizowany wątek zawiesił już swoje wykonanie w oczekiwaniu na sygnał, w przeciwieństwie do procesu, który po prostu zostaje przerwany i trwa.

+7

To jest zupełnie inne niż sygnały. Chociaż zgodziłbym się, że jest to zwykle lepsze podejście, myślę, że "pthread_kill" jest odpowiedzią na pytanie OP. –

+2

@R ..: Właściwie to pytanie nie jest zbyt jasne i założyłem, że autor nie pyta o dostarczanie sygnałów systemu operacyjnego do konkretnego wątku, ale raczej o wysyłanie sygnałów między wątkami. –

0

nie jestem pewien, że to jest możliwe, ponieważ jest to platforma i zależna od implementacji i bardzo proponuję nie używać sygnałów do komunikacji między wątkami. Czasami tylko określony wątek będzie odbierać sygnały, a czasami wszystkie wątki odbierają sygnały.

Lepsze mechanizmy komunikacji między wątkami istnieją, jak kolejki, semafory i blokady.

2

Sygnały nie mają powinowactwa wątku. Są one obsługiwane całkowicie asynchronicznie. Po określeniu obsługi sygnału za pomocą signal(2) lub sigaction(2), jest to globalna procedura obsługi sygnału. Kiedy sygnał jest podniesiony, procedura obsługi sygnału działa na szczycie stosu, niezależnie od tego, która wątek działa w tym czasie, i nie możesz tego kontrolować.

Wygląda na to, że chcesz mieć coś w rodzaju komunikacji międzywymiarowej. Najprostszym sposobem na to jest ze zmienną volatile shared:

volatile bool should_terminate = false; 

void ChildThread() 
{ 
    while(!should_terminate) 
    { 
     // do stuff 
    } 
} 

void MainThread() 
{ 
    // To terminate child thread: 
    should_terminate = true; 
} 

Jeśli potrzebujesz silniejszej kontroli współbieżności, zajrzeć do muteksy, zmiennych stanu, i semafory.

7

Sygnały są wysyłane do procesu jako całości. Każdy sygnał wysłany do procesu jest odbierany przez pojedynczy wątek (w imieniu całego programu). Istnieją maski sygnałów na wątek, które mają wpływ na to, czy dany wątek może obsłużyć konkretny sygnał.

Potrzebny jest więc program obsługi sygnału - prawdopodobnie w jednym wątku. Zauważ, że istnieją ograniczenia co do tego, co powinieneś zrobić w obsłudze sygnału wątku. Uważaj, aby nie przekroczyć obietnic złożonych przez standard (które są minimalne).

Jednak funkcja pthread_kill() może być używana do wysyłania sygnałów do innych wątków, o ile bieżący wątek może zidentyfikować (ma dostęp do wartości identyfikatora wątku (pthread_t), które identyfikują) wątki, które wciąż są wykonywane w procesie. Możesz zdecydować o przekazaniu sygnału do innych wątków, używając innego numeru sygnału od pierwotnie złapanego (tak, że jeden wątek odbiera sygnał zewnętrzny, ale wiele wątków odbiera sygnał wewnętrzny). Lub możesz użyć innej synchronizacji Pthread lub podstawowej komunikacji zamiast sygnałów.

+0

Chciałbym wyjaśnić "ma dostęp do identyfikatora wątku". Jeśli chodzi o poprawność formalną, nawet jeśli masz zapisane 'pthread_t', to jest ono nieważne (niezdefiniowane zachowanie), aby użyć go, jeśli wątek mógł zostać zakończony w stanie odłączonym lub z innym wątkiem, który już na nim wywołuje' pthread_join'. –