2013-09-24 3 views
1

Я новичок в C. Я хочу создать программу с двумя потоками, которые будут посылать сигналы (SIGUSR1 и SIGNUSR2) в цикле и четыре потока, которые будут ждать этих сигналов и обрабатывать их.Thread wait for Signal in loop

Я понял, что отправлю сигнал, который мне нужно сделать: kill(getpid,SIGUSR1);, но как я создаю четыре потока, которые будут ждать сигнала? сигнал регистрируется на определенную функцию. Как четыре потока будут ждать одного и того же сигнала?

Могу ли я использовать другие потоки, проверяя также тип сигнала (не останавливая сигнал для достижения других потоков)?

Спасибо.


Update:
Я пытаюсь иметь четыре потока ожидания для сигналов, когда два потока посылают сигналы, нити не знают, какой поток будет ловить сигнал. Я не хочу указывать идентификатор потока, который получит сигнал.

При использовании pthread_kill() Мне нужно указать идентификатор потока (который я пытаюсь не делать).

+0

Есть ли причина, по которой вам нужно использовать сигналы (что похоже на проблему синхронизации)? – jev

+0

Что вы подразумеваете под «случайным процессом»?Вы можете настроить сигнальные маски на поток, чтобы разрешить сигналу достичь определенных потоков, а затем использовать 'kill', чтобы ядро ​​выбрало произвольный случайный поток для приема сигнала. Или вы можете активно перечислять все свои потоки, использовать генератор случайных чисел, чтобы выбрать из них, и отправить направленный сигнал. –

+0

@ KerrekSB, могу ли я отправить сигнал на два процесса одновременно, и который когда-либо свободен, будет обрабатывать сигнал? Или я могу создать несколько процессов, принадлежащих к одной группе, и отправить сигнал всей группе? – Mike

ответ

2

Обновление: Этот ответ, вероятно, частично бесполезен. Вы должны использовать pthread_kill для отправки сигналов в определенный поток. Я оставлю его на случай, если кто-то найдет что-нибудь в нем.


В Linux потоки не могут быть обработаны с kill, так как kill пошлет сигнал на любой случайный поток, который не блокирует сигнал.

Вместо этого вы хотите получить системный вызов tgkill, который предназначен для определенного потока. Какой поток? Вы узнаете системный вызов gettid.

К сожалению, glibc не предоставляет обертки для этих двух системных вызовов. Нет проблем, вы не можете писать те себя:

#include <signal.h> 
#include <sys/syscall.h> 
#include <sys/types.h> 

pid_t gettid() 
{ 
    return syscall(SYS_gettid); 
} 

int tgkill(int sig, pid_t pgid, pid_t tid) 
{ 
    return syscall(SYS_tkill, sig, pgid, tid); 
} 

Первый аргумент tgkill является сигналом, так как для kill. Второй - это группа потоков id, которая совпадает с процессом процесса вашего процесса (доступна с getpid). Последний аргумент - это идентификатор потока ядра, который вы получаете с помощью gettid и который также составляет каталоги в /proc/<pid>/task/ на Linux.

Наконец, вы должны иметь возможность дождаться появления сигнала. Вы можете сделать это путем блокирования сигнала в потоке с pthread_sigmask, а затем с помощью sigwaitinfo or sigtimedwait:

// block signal 
sigset_t newset, oldset; 
sigemptyset(&nweset); 
sigaddset(&newset, SIGUSR1); 
pthread_sigmask(SIG_BLOCK, &newset, &oldset); 

// wait 
sigwaitinfo(&newset, NULL); 

// restore previous signal mask 
pthread_sigmast(SIG_SETMASK, &oldset, NULL); 
+0

Спасибо за отличный ответ. Но я должен указать поток, к которому я посылаю сигнал? как я узнаю, какой поток поймает его? Также, как отправить сигнал в цикле? – Mike

+0

@Mike: Используя 'gettid' в нужной теме! Я не уверен, что вы можете получить идентификатор потока в * другом * потоке. Вы можете перечислить '/ proc//task /' и исключить свой собственный идентификатор потока, чтобы узнать, что это за остальные. Или каждый новый поток посылает сигнал обратно (проверьте документы, вы можете добавить данные в часть siginfo). –

+0

Простое сохранение идентификаторов потоков при их создании - еще один очевидный вариант. –

0

я действительно не рекомендовал бы использовать SIGUSR сигналы для синхронизации потоков. Если вы хотите, чтобы pthreads подождали по сигналу, я бы посмотрел на страницы руководства для pthread_cond_signal