每个线程都有自己的信号屏蔽字,但是信号的处理是进程中所有线程共享的。
进程中的信号是递送给单个线程的。
多线程中使用函数pthread_sigmask来阻止信号发送。
线程可以通过sigwait等待一个或者多个信号的出现。
int sigwait(const sigset_t *restrict set, int *restrict signop);
set指定了线程等待的信号集,返回时,signop指向的整数将包含发送信号的数量。
如果信号集中的某个信号在sigwait调用的时候处于挂起状态(未处理),那么sigwait将无阻塞地返回。在返回之前,sigwait将从进程中移除那些处于挂起等待状态的信号。
sigwait函数监听被阻塞的信号,如果所监听的信号产生了,则将其从未决队列中移出来并返回
一个demo:
#include "apue.h"
#include <pthread.h>
int quitflag; //set nonzero by thread
sigset_t mask;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t waitloc = PTHREAD_COND_INITIALIZER;
void *thr_fn(void *args)
{
int err, signo;
for (; ;)
{
err = sigwait(&mask, &signo);//sigwait函数监听被阻塞的信号,如果所监听的信号产生了,则将其从未决队列中移出来并返回
if (err != 0)
{
err_exit(err, "sigwait failed");
}
switch (signo)
{
case SIGINT:
printf("\ninterrupt\n");
break;
case SIGQUIT:
pthread_mutex_lock(&lock);
quitflag = 1;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&waitloc);
return 0;
default:
printf("unexpected signal %d\n", signo);
exit(1);
}
}
}
int main()
{
int err;
sigset_t oldmask;
pthread_t tid;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
if ((err = pthread_sigmask(SIG_BLOCK, &mask, &oldmask)) != 0)
{
err_exit(err, "SIG_BLOCK error");
}
err = pthread_create(&tid, NULL, thr_fn, 0);
if (err != 0)
{
err_exit(err, "can't create thread");
}
pthread_mutex_lock(&lock);
while (quitflag == 0)
{
pthread_cond_wait(&waitloc, &lock);//pthread_cond_wait函数先解锁lock,待条件变量满足收到信号之后返回再次锁上lock
}
pthread_mutex_unlock(&lock);
//SIGQUIT has been caught and is now blocked; do whatever.
quitflag = 0;
//reset signal mask which unblocks SIGQUIT.
if ((sigprocmask(SIG_SETMASK, &oldmask, NULL)) < 0)
{
err_sys("SIG_SETMASK error");
}
exit(0);
};