int pthread_kill(pthread_t thread, int sig);
发送信号
如果sig是0,则无信号发送,但可以用来检测线程是否还活着。SIGQUIT是终止。
返回值:
ESRCH 线程已结束
EINVAL 线程还存在
int sigaction(int signum, const struct sigaction act, struct sigaction oldact);
给信号sig设置一个处理函数,处理函数再sigaction中指定。类似进程中的signal
act.sa_mask 信号屏蔽字
act.sa_handler 信号集处理程序。
参数:signum,信号的名字
act,传入新的处理方式,指针非空, 则修改信号的动作;
oldact,传出旧的处理方式,指针非空, 则返回该信号的上一个动作.
返回值:成功返回0,失败返回错误码
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
}
sa_handler:指定信号捕捉后的处理函数名,也可以赋值为SIG_IGN表示忽略或SIG_DFT表示执行默认操作
sa_mask:调用信号处理函数时,所要屏蔽的信号集合(信号屏蔽字)。
注意:仅在处理函数被调用期间屏蔽生效,是临时性设置。用sigaddset函数添加需要被捕捉的信号。
sa_flags:通常设置为0,表示使用默认属性,为0的时候,可以屏蔽正在处理的信号(若在处理二号信号的时候又有二号信号,则此时传来的二号信号就会被屏蔽)
使用:
int sigenptyset(sigset_t set);
-清空信号集
int sigfillset(sigset_t set);
-将所有信号加入信号集
int sigaddset(sigset_t set, int signum);
-增加一个信号到信号集
int sigdelset(sigset_t set,int signum);
-删除一个信号到信号集
void sig_handler1(int arg)
{
printf("thread1 get signal\n");
return;
}
void *thread_fun1(void *arg)
{
/*
1.定义act结构体
2. 添加SIGQUIT信号到屏蔽信号集,将SIGQUIT 屏蔽
3.将SIGQUIT以新函数代替
( 需要设置act里的屏蔽信号集和处理信号)
*/
struct sigaction act;
memset(&act,0,sizeof(act));
sigaddset(&act.as_mask,SIGQUIT); //添加SIGQUIT信号到屏蔽信号集
act.sa_handler = sig_handler1;//指定信号捕捉后的处理函数名
sigaction(SIGQUIT, &act,NULL); //将SIGQUIT信号 以act
}
多线程信号屏蔽处理。
int pthread_sigmask(int how,const sigset_t *set, sigset_t *oldset)
how=SIG_BLOCK :向当前的信号掩码中添加set,其中set表示要阻塞的信号组
SIG_BLOCK 删除set
SIG-SETMASK 替换为set
实例
#include "stdio.h"
#include "pthread.h"
#include "stdlib.h"
#include "signal.h"
#include "string.h"
#include "unistd.h"
void sig_handler1(int arg)
{
printf("thread1 get signal\n");
return;
}
void sig_handler2(int arg)
{
printf("thread2 get signal\n");
return;
}
void *thread_fun1(void *arg)
{
printf("new thread 1\n");
struct sigaction act;
memset(&act,0,sizeof(act));
sigaddset(&act.sa_mask,SIGQUIT);
act.sa_handler = sig_handler1;
sigaction(SIGQUIT, &act,NULL);
pthread_sigmask(SIG_BLOCK,&act.sa_mask,NULL);//删除添加的屏蔽信号组sa_mask
sleep(2);
}
void *thread_fun2(void *arg)
{
printf("new thread 2\n");
struct sigaction act;
memset(&act,0,sizeof(act));
sigaddset(&act.sa_mask,SIGQUIT);
act.sa_handler = sig_handler2;
sigaction(SIGQUIT, &act,NULL);
//pthread_sigmask(SIG_BLOCK,&act.sa_mask,NULL);
sleep(2);
}
int main()
{
pthread_t tid1 ,tid2;
int err;
int s;
err =pthread_create(&tid1,NULL,thread_fun1,NULL);
if(err!=0)
{
printf("create tid1 failed\n") ;
return -1;
}
err =pthread_create(&tid2,NULL,thread_fun2,NULL);
if(err!=0)
{
printf("create tid2 failed\n") ;
return -2;
}
sleep(1);
s =pthread_kill(tid1 ,SIGQUIT);
if(s!=0)
{
printf("send signal to thread1 failed\n");
}
s =pthread_kill(tid2 ,SIGQUIT);
if(s!=0)
{
printf("send signal to thread2 failed\n");
}
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
结果:可能会出现thread2 get signal 或thread1 get signal
因为sigaction的作用是最后一次定义的,有可能是handler1或handler2,所以main中发送SIGQUIT信号时,有两种情况发生。
0表示不执行,非0为执行;这个参数并不影响异常终止时清理函数的执行(及当pthread_cleanup_pop()函数的参数为0时,仅仅在线程调用pthread_exit函数或者其它线程对本线程调用 pthread_cancel函数时,才在弹出“清理函数”的同时执行该“清理函数”)。
这两个函数要成对出现,否则编译无法通过。
当执行以下操作时调用清理函数,清理函数的参数由arg传入
#include "stdio.h"
#include "pthread.h"
#include "stdlib.h"
#include "signal.h"
#include "string.h"
#include "unistd.h"
void *first_clean(void *arg) //处理函数1
{
printf("%s first clean\n",arg);
return(void *)0;
}
void *second_clean(void *arg)//处理函数2
{
printf("%s second clean\n",arg);
return(void *)0;
}
void * thread_fun1(void *arg)
{
printf("new thread 1\n");
pthread_cleanup_push(first_clean, "thread1");//注册处理函数1
pthread_cleanup_push(second_clean,"thread1");//注册处理函数2
pthread_cleanup_pop(1); //调用执行second clean
pthread_cleanup_pop(0); //为0 不执行first clean
return(void *)1;
}
void *thread_fun2(void *arg)
{
printf("new thread 2\n");
pthread_cleanup_push(first_clean, "thread2");
pthread_cleanup_push(second_clean,"thread2");
pthread_exit((void *)2);//会执行first clean 和second clea 虽然pop的参数是0
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
}
int main()
{
pthread_t tid1,tid2;
int err;
err=pthread_create(&tid1,NULL,thread_fun1,NULL);
if(err !=0)
{
printf("create nwe thread 1 failed\n");
return -1;
}
err=pthread_create(&tid2,NULL,thread_fun2,NULL);
if(err !=0)
{
printf("create nwe thread 2 failed\n");
return -1;
}
sleep(2);
return 0;
}