【Linux多线程编程-自学记录】06.向线程发送信号-sigaction

Linux多线程编程学习代码(代码已上传gitee,还请各位兄弟点个Star哦!)

https://gitee.com/chenshao777/linux_thread.git


笔记:
1.线程信号处理:
int sigaction(int signum,
const struct sigaction *act,
struct sigaction *oldact);
函数功能:给signum信号设置一个处理函数,处理函数在struct 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 pthread_sigmask(int how,
const sigset_t *set,
sigset_t *oldset);
how = SIG_BLOCK: 向当前的信号掩码中添加set,其中set表示要阻塞的信号组
SIG_UNBLOCK: 向当前的信号掩码中删除set,其中set表示要取消阻塞的信号组
SIG_SETMASK: 将当前的信号掩码替换为set,其中set表示新的信号掩码

**PS:**在多线程中,新线程的当前信号掩码会继承创造它的线程的信号掩码

一般情况下,被阻塞的信号将不能中断此线程的执行,除非此信号的产生是因为程序运行出错,如SIGSEGC;
另外信号SIGKILL和SIGSTOP无法被阻塞。


spu.h文件

#ifndef _SPU_H_
#define _SPU_H_

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<signal.h>
#include<errno.h>

#endif

06.thread_mask.c文件

/*
  1.创建2个线程
  2.线程1调用 pthread_sigmask 屏蔽 SIGQUIT 信号,延时,等待线程2先执行完,使线程1最后执行 sigaction 
  3.线程2不屏蔽 SIGQUIT 信号
  4.线程1屏蔽了 SIGQUIT 信号,但是信号处理函数仍热执行了
  5.发现 sigaction 函数以最后调用的线程为准
*/

#include "spu.h"

void sig_handler1()
{
    
    
    printf("this is handler01\n");
}

void sig_handler2()
{
    
    
    printf("this is handler02\n");
}

void *thread_fun1(void *arg)
{
    
    
    sleep(1);  // 延时,等待线程2先执行完,使线程1最后执行 sigaction 
    printf("I am thread01\n");

    struct sigaction act;
    memset(&act, 0, sizeof(act));
    // 添加SIGQUIT信号到信号集
    sigaddset(&act.sa_mask, SIGQUIT);
    // 设置信号处理函数
    act.sa_handler = sig_handler1;
    // 设置线程信号处理
    sigaction(SIGQUIT, &act, NULL);

    // 屏蔽信号
    pthread_sigmask(SIG_BLOCK, &act.sa_mask, NULL);

    sleep(3);
    return (void*)1;
}


void *thread_fun2(void *arg)
{
    
    
    printf("I am thread02\n");

    struct sigaction act;
    memset(&act, 0, sizeof(act));
    // 添加SIGQUIT信号到信号集
    sigaddset(&act.sa_mask, SIGQUIT);
    // 设置信号处理函数
    act.sa_handler = sig_handler2;
    // 设置线程信号处理
    sigaction(SIGQUIT, &act, NULL);

    // 屏蔽信号
    //pthread_sigmask(SIG_BLOCK, &act.sa_mask, NULL);

    sleep(3);
    return (void*)2;
}


int main()
{
    
    
    int err1,err2;
    pthread_t tid1, tid2;
    void *__retval;

    err1 = pthread_create(&tid1, NULL, thread_fun1, NULL);
    if(err1 != 0)
    {
    
    
        printf("thread1 create failed\n");
        return 0;
    }

    err2 = pthread_create(&tid2, NULL, thread_fun2, NULL);
    if(err2 != 0)
    {
    
    
        printf("thread2 create failed\n");
        return 0;
    }

    sleep(2);
    // 向线程1发送SIGQUIT信号
    pthread_kill(tid1, SIGQUIT);
    // 向线程2发送SIGQUIT信号
    pthread_kill(tid2, SIGQUIT);

    // 链接线程1
    printf("pthread_join1 return %d\n",pthread_join(tid1, NULL));
    // 链接线程2
    printf("pthread_join2 return %d\n",pthread_join(tid2, NULL));


    pthread_exit(__retval);
}

06.thread_signal.c文件

/*
  1.创建一个线程
  2.1 sleep(1)后,向线程发送一个信号0,此时发送信号失败
  2.2 线程中先sleep(1),main中发送一个SIGQUIT信号,直接退出整个进程,没有任何打印信息
*/

#include "spu.h"

void *thread_fun1(void *arg)
{
    
    
    sleep(1);

    printf("I am thread 1\n");
	return (void*)0;
}

int main(int argc, char *argv[])
{
    
    	
	int err1;
	pthread_t thread_id1; 
    int s;

    void *__retval;

	err1 = pthread_create(&thread_id1, NULL, thread_fun1, NULL);

	if(err1 != 0)
		printf("create failed!\n");
	else
		printf("create success!\n");

    s = pthread_kill(thread_id1, SIGQUIT);  //由于线程没有作任何信号处理,退出整个进程
    
    //由于线程退出,所以找不到线程
    if(s == ESRCH)
        printf("thread is not found\n"); 

    pthread_exit(__retval);
}

猜你喜欢

转载自blog.csdn.net/HuangChen666/article/details/130458030