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

news/2024/5/18 23:18:57 标签: linux, 信号, signal

笔记:
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);
}

http://www.niftyadmin.cn/n/280618.html

相关文章

Servlet 笔记

1. HTTP 协议 1.1 HTTP协议简介 超文本传输协议&#xff08;英文&#xff1a;HyperText Transfer Protocol&#xff0c;缩写&#xff1a;HTTP&#xff09;是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网的数据通信的基础。 HTTP的发展是由蒂姆伯纳斯-…

【Java笔试强训 30】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;最难的问…

【HTML5笔记】HTML5语义化标签、音视频标签、表单标签属性

目录 一、HTML5学习 1.1、HTML5语法 1.2、语义化标签 1.3、音视频标签 &#xff08;1&#xff09;音频标签 &#xff08;2&#xff09;视频标签 1.4、input标签type属性 1.5、datalist数据列表 1.6、表单属性 一、HTML5学习 1.1、HTML5语法 HTML5增加了很多的新标签…

汇编语言学习笔记一

常用寄存器类型 通用寄存器 AX&#xff0c;BX&#xff0c;CX&#xff0c;DX&#xff0c;这四个寄存器都是16位的 他们也可以拆分为2个8位的寄存器&#xff0c;如AX可以拆分为AH和AL两个8位的寄存器&#xff0c;其它三个也可以如此。 通用寄存器的使用比较简单&#xff0c;如 …

14-5-进程间通信-信号

一、信号的基本概述 1.什么是信号&#xff1f; &#xff08;1&#xff09;对于linux来说&#xff0c;信号是软中断。比如在终端输入ctrlc来中断正在运行的程序&#xff0c;原理是linux通过信号机制来停止一个程序。 &#xff08;2&#xff09;每一个信号都有一个名字和编号&…

多线程、协程和多进程并发编程

37.1 如何通俗理解线程和进程&#xff1f; 进程&#xff1a;进程就是正在执⾏的程序。 线程&#xff1a;是程序执⾏的⼀条路径, ⼀个进程中可以包含多条线程。 通俗理解&#xff1a;例如你打开抖⾳&#xff0c;就是打开⼀个进程&#xff0c;在抖⾳⾥⾯和朋友聊天就是开启了⼀条…

Three.js--》Gsap动画库基本使用与原理

目录 Gsap动画库使用讲解 Gsap动画库基本使用 修改自适应画面及双击进入全屏 设置stats性能监视器 Gsap动画库使用讲解 GSAP的全名是GreenSock Animation Platform&#xff0c;是一个从flash时代一直发展到今天的专业动画库&#xff0c;今天将其与three.js进行结合&#x…

软件服务架构SOA EDA

面向服务的架构&#xff08;Service-Oriented Architecture&#xff0c;SOA&#xff09; SOA是一种基于服务的架构方法&#xff0c;它将软件系统划分为独立的服务&#xff0c;并通过标准化的接口和协议进行通信和集成。SOA具有以下特点&#xff1a; 松耦合&#xff1a;SOA中的…