当前位置: 首页 > news >正文

POSIX线程使用signal模拟“中断“处理流程

一. 中断/信号处理流程示意图

二.POSIX线程信号处理流程说明

1. 与中断handler对应的,信号也有handler。每个特定的中断对应一个handler,每个特定的信号也对应一个handler。

2. 中断通过硬件或者int指令等方式触发handler执行,信号通过pthread_kill向某个线程发送信号触发handler执行。该线程收到信号后,会打断当前执行流并跳转到信号handler执行,之后返回到当前执行流。

三.POSIX线程信号API和数据结构

1.sigaction

sigaction ———— 查询或设置信号处理方式
(1)头文件
    #include<signal.h>
(2)函数原型
    int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);
    sigaction()会根据参数signum指定的信号编号来设置该信号的处理函数。参数signum可以指定SIGKILL和SIGSTOP以外的所有信号。
(3)数据结构
    struct sigaction
    {
       void (*sa_handler) (int);
       sigset_t sa_mask;
       int sa_flags;
       void (*sa_restorer) (void);
    }
sa_handler此参数和signal()的参数handler相同,代表新的信号处理函数,其他意义请参考signal()。
sa_mask 用来设置在处理该信号时暂时将sa_mask 指定的信号搁置。
sa_restorer 此参数没有使用。
sa_flags 用来设置信号处理的其他相关操作,下列的数值可用。

2.sigfillset

sigfillset ———— 将所有信号加入此信号集
(1)头文件
    #include<signal.h
(2)函数原型
    int sigfillset(sigset_t * set);
    sigfillset()用来 将参数set信号集初始化,然后把所有的信号加入到此信号集里。

3.sigemptyset

sigemptyset ———— 初始化信号集
(1)头文件
    #include<signal.h>
(2)函数原型
    int sigemptyset(sigset_t *set);
    sigemptyset()用来将参数set信号集初始化并清空。

4.pthread_sigmask

pthread_sigmask ———— 更改或检查调用线程的信号掩码
(1)头文件
    #include <pthread.h>
    #include<signal.h>
(2)函数原型
    int pthread_sigmask(int how, const sigset_t *new, sigset_t *old);
 
how用来确定如何更改信号组,可以为以下值之一:
SIG_BLOCK:向当前的信号掩码中添加new,其中new表示要阻塞的信号组。
SIG_UNBLOCK:向当前的信号掩码中删除new,其中new表示要取消阻塞的信号组。
SIG_SETMASK:将当前的信号掩码替换为new,其中new表示新的信号掩码。

5.pthread_kill

pthread_kill ———— 向线程发送信号
(1) 头文件
    #include <pthread.h>
    #include<signal.h>
(2)函数原型
    int pthread_kill(thread_t tid, int sig);
    pthread_kill() 将信号sig发送到由tid指定的线程。tid所指定的线程必须与调用线程在同一个进程中。

四.示例程序

#include <pthread.h>
#include <stdio.h>
#include <sys/signal.h>

#define NUMTHREADS 3
void sighand(int signo);

void *threadfunc(void *parm)
{
    pthread_t             tid = pthread_self();
    int                   rc;

    printf("Thread %u entered/n", tid);
    rc = sleep(30); /* 若有信号中断则返回剩余秒数 */
    printf("Thread %u did not get expected results! rc=%d/n", tid, rc);
    return NULL;
}

void *threadmasked(void *parm)
{
    pthread_t             tid = pthread_self();
    sigset_t              mask;
    int                   rc;

    printf("Masked thread %lu entered/n", tid);

    sigfillset(&mask); /* 将所有信号加入mask信号集 */

    /* 向当前的信号掩码中添加mask信号集 */
    rc = pthread_sigmask(SIG_BLOCK, &mask, NULL);
    if (rc != 0)
    {
        printf("%d, %s/n", rc, strerror(rc));
        return NULL;
    }

    rc = sleep(15);
    if (rc != 0)
    {
        printf("Masked thread %lu did not get expected results! rc=%d /n", tid, rc);
        return NULL;
    }
    printf("Masked thread %lu completed masked work/n", tid);
    return NULL;
}

int main(int argc, char **argv)
{
    int                     rc;
    int                     i;
    struct sigaction        actions;
    pthread_t               threads[NUMTHREADS];
    pthread_t               maskedthreads[NUMTHREADS];

    printf("Enter Testcase - %s/n", argv[0]);
    printf("Set up the alarm handler for the process/n");

    memset(&actions, 0, sizeof(actions));
    sigemptyset(&actions.sa_mask); /* 将参数set信号集初始化并清空 */
    actions.sa_flags = 0;
    actions.sa_handler = sighand;

    /* 设置SIGALRM的处理函数 */
    rc = sigaction(SIGALRM,&actions,NULL);

    printf("Create masked and unmasked threads/n");
    for(i=0; i<NUMTHREADS; ++i)
    {
        rc = pthread_create(&threads[i], NULL, threadfunc, NULL);
        if (rc != 0)
        {
            printf("%d, %s/n", rc, strerror(rc));
            return -1;
        }

        rc = pthread_create(&maskedthreads[i], NULL, threadmasked, NULL);
        if (rc != 0)
        {
            printf("%d, %s/n", rc, strerror(rc));
            return -1;
        }
    }

    sleep(3);
    printf("Send a signal to masked and unmasked threads/n");

     /* 向线程发送SIGALRM信号 */
    for(i=0; i<NUMTHREADS; ++i)
    {
        rc = pthread_kill(threads[i], SIGALRM);
        rc = pthread_kill(maskedthreads[i], SIGALRM);
    }

    printf("Wait for masked and unmasked threads to complete/n");
    for(i=0; i<NUMTHREADS; ++i) {
        rc = pthread_join(threads[i], NULL);
        rc = pthread_join(maskedthreads[i], NULL);
    }

    printf("Main completed/n");
    return 0;
}

void sighand(int signo)
{
    pthread_t             tid = pthread_self();

    printf("Thread %lu in signal handler/n", tid);
    return;
}

参考:

POSIX 线程 – pthread_sigmask - Prayer - C++博客 (cppblog.com)

相关文章:

  • 深入Spring Boot :整合Redis详解
  • 检测数据类型
  • java多线程面试总结,字节跳动java面试题
  • python读取json格式文件大量数据,以及python字典和列表嵌套用法详解
  • 前端新特性
  • 有什么低价好用的电容笔推荐?大一新生必备物品
  • Vite打包优化插件
  • 一文搞懂nginx的反向代理 负载均衡
  • Redis的哨兵模式搭建
  • 闭包、闭包应用场景
  • 瑞吉外卖 —— 2、后台登录和登出
  • 阿里云配置hadoop远程连接Web页面(如50070端口)
  • Linux 任务调度
  • Github每日精选(第32期):HTML智能仪表盘tabler
  • 对多个 CSV 文件做关联
  • maya建模与骨骼动画快速实现人工鱼
  • Odoo domain写法及运用
  • Vue2.0 实现互斥
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 聊聊hikari连接池的leakDetectionThreshold
  • 巧用 TypeScript (一)
  • 如何设计一个比特币钱包服务
  • 推荐一个React的管理后台框架
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 1.Ext JS 建立web开发工程
  • ​马来语翻译中文去哪比较好?
  • # Pytorch 中可以直接调用的Loss Functions总结:
  • #LLM入门|Prompt#3.3_存储_Memory
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (007)XHTML文档之标题——h1~h6
  • (JS基础)String 类型
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (译)2019年前端性能优化清单 — 下篇
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .a文件和.so文件
  • .net core使用ef 6
  • .NET Core中的去虚
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】
  • .net项目IIS、VS 附加进程调试
  • ::什么意思
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [04]Web前端进阶—JS伪数组
  • [Android]Android P(9) WIFI学习笔记 - 扫描 (1)
  • [Angular 基础] - 指令(directives)
  • [BZOJ 4129]Haruna’s Breakfast(树上带修改莫队)
  • [C#]winform部署yolov9的onnx模型
  • [Django 0-1] Core.Checks 模块
  • [LeetBook]【学习日记】获取子字符串 + 颠倒子字符串顺序
  • [MySQL]视图索引以及连接查询案列
  • [oeasy]python0002_终端_CLI_GUI_编程环境_游戏_真实_元宇宙