Linux多线程3-4_向线程发送信号
⼀、发送信号的函数
int pthread_kill(pthread_t thread, int sig);
1、别被名字吓到,pthread_kill可不是kill,⽽是向线程发送signal。还记得signal吗,⼤部分signal的默认动作是终⽌进程的运⾏,所以,我们才要⽤sigaction()去抓信号并加上处理函数。
2、向指定ID的线程发送sig信号,如果线程代码内不做处理,则按照信号默认的⾏为影响整个进程,也就是说,如果你给⼀个线程发送了SIGQUIT,但线程却没有实现signal处理函数,则整个进程退出。如果要获得正确的⾏为,就需要在线程内实现sigaction了。所以,如果int sig的参数不是0,那⼀定要清楚到底要⼲什么,⽽且⼀定要实现线程的信号处理函数,否则,就会影响整个进程。如果int sig是0呢,这是⼀个保留信号,其实并没有发送信号,作⽤是⽤来判断线程是不是还活着。
⼆、信号处理
1、进程信号处理:
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
给信号signum设置⼀个处理函数,处理函数在sigaction中指定
act.sa_mask 信号屏蔽字
act.sa_handler 信号集处理程序
2、信号集的处理
int sigemptyset(sigset_t *set);//清空信号集
int sigfillset(sigset_t *set);//将所有信号加⼊信号集
int sigaddset(sigset_t *set,int signum);//增加⼀个信号到信号集
int sigdelset(sigset_t *set,int signum);//删除⼀个信号到信号集
3、多线程信号屏蔽处理
/* int sigprocmask(int how, const sigset_t *set, sigset_t oldset)/这是进程的信号屏蔽处理
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
how = SIG_BLOCK:向当前的信号掩码中添加set,其中set表⽰要阻塞的信号组。
SIG_UNBLOCK:向当前的信号掩码中删除set,其中set表⽰要取消阻塞的信号组。linux下的sleep函数
SIG_SETMASK:将当前的信号掩码替换为set,其中set表⽰新的信号掩码。
在多线程中,新线程的当前信号掩码会继承创造它的线程的信号掩码。
⼀般情况下,被阻塞的信号将不能中断此线程的执⾏,除⾮此信号的产⽣是因为程序运⾏出错如 SIGSEGV;另外不能被忽略处理的信号SIGKILL 和 SIGSTOP 也⽆法被阻塞。
三、实例
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<iostream>
#include<signal.h>
#include<errno.h>
#include"include/pthread.h"
#ifndef _WIN64
#pragma comment(lib,".\\lib32\\pthreadVC2.lib")
#pragma comment(lib,".\\lib32\\pthreadVCE2.lib")
#pragma comment(lib,".\\lib32\\pthreadVSE2.lib")
#else
#pragma comment(lib,".\\lib64\\pthreadVC2.lib")
#endif
/*
WINDOWS 缺少库函数,得在Linux下运⾏
*DECRIPTION:    正确到处理信号
*    int pthread_kill(pthread_t thread, int sig);
*        向线程thread发送sig信号,成功返回0,失败返回错误码
*
*    int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
*        为信号signum设置处理函数,处理函数在sigaction中指定
*        act.sa_mask 信号屏蔽字
*        act.sa_handler 信号集处理程序
*
* int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
*        多线程信号屏蔽函数
*        how = SIG_BLOCK:向当前的信号掩码中添加set,其中set表⽰要阻塞的信号组。*        SIG_UNBLOCK:向当前的信号掩码中删除set,其中set表⽰要取消阻塞的信号组。* SIG_SETMASK:将当前的信号掩码替换为set,其中set表⽰新的信号掩码。
* 在多线程中,新线程的当前信号掩码会继承创造它的线程的信号掩码
*/
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);
Sleep(2);
return(void*)0;
}
void*thread_fun2(void*arg)
{
printf("new thread 2\n");
//WINDOWS 缺少库函数,得在Linux下运⾏
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 err;
int s;
err =pthread_create(&tid1,NULL,thread_fun1,NULL); if(err!=0)
{
printf("create new thread 1 failed\n");
return0;
}
err =pthread_create(&tid2,NULL,thread_fun2,NULL); if(err !=0)
{
printf("create new thread 2 failed\n");
return0;
}
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);
return0;
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。