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表示要取消阻塞的信号组。
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 s;

	err = pthread_create(&tid1,NULL,thread_fun1,NULL);
	if (err!=0)
	{
		printf("create new thread 1 failed\n");
		return 0;
	}
	err = pthread_create(&tid2,NULL,thread_fun2,NULL);
	if (err != 0)
	{
		printf("create new thread 2 failed\n");
		return 0;
	}

	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;
}

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值