前言
本章主要介绍线程中的信号。
一、pthread_sigmask
#include <signal.h>
int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
pthread_sigmask函数与sigprocmask函数基本相同,不过pthread_sigmask工作在线程中。
set 参数包含线程用于修改信号屏蔽字的信号集。
how参数可以取下列3个值之一:SIG_BLOCK,把信号集添加到线程信号屏蔽字中;SIG_SETMASK,用信号集替换线程的信号屏蔽字;SIG_UNBLOCK,从线程信号屏蔽字中移除信号集
oset参数不为空,线程之前的信号屏蔽字就存储在它指向的sigset_t结构中。
二、sigwait
#include <signal.h>
int sigwait(const sigset_t *restrict set, int *restrict signop);
线程可以通过sigwait等待一个或者多个信号的出现。
set参数指定了线程等待的信号集。
返回时,signop指向的整数将包含发送信号的数量。
如果信号集中的某个信号在sigwait调用的时候处于挂起状态(信号已经产生但是还未被传送),那么sigwait将无阻塞的返回。在返回之前,sigwait将从进程中移除那些处于挂起状态的信号。
三、pthread_kill
#include <signal.h>
int pthread_kill(pthread_t thread, int signo);
把信号发送给进程,可以调用kill。要把信号发送给线程,可以调用pthread_kill。
可以传送一个0值的signo来检擦线程是否存在。如果信号的默认动作是终止改进程,那么把信号传递给某个线程仍然会杀死整个进程。
注意:闹钟定时器是进程资源,所有线程共享相同的闹钟。
四、实例
1.同步信号处理
代码如下(示例):
int quitflag;
sigset_t mask;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t waitloc = PTHREAD_COND_INITIALIZER;
void *thr_fn3(void *arg)
{
int err,signo;
for(;;){
err = sigwait(&mask,&signo);
if(err != 0)
err_exit(err,"sigwait failed");
switch(signo){
case SIGINT:
printf("\ninterrupt\n");
break;
case SIGQUIT:
printf("\nsigquit\n");
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);
}
}
}
void unix_12_16_pthread_signal(void)
{
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_fn3,0);
if(err != 0)
err_exit(err,"can't create error");
pthread_mutex_lock(&lock);
while(quitflag == 0)
pthread_cond_wait(&waitloc,&lock);
pthread_mutex_unlock(&lock);
quitflag = 0;
if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0)
err_sys("SIG_SETMASK error");
exit(0);
}
总结
本章主要介绍了线程信号以及给出了线程同步实例。