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


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

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

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

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

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

    1.sigaction

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

    2.sigfillset

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

    3.sigemptyset

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

    4.pthread_sigmask

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

    5.pthread_kill

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

    四.示例程序

    1. #include
    2. #include
    3. #include
    4. #define NUMTHREADS 3
    5. void sighand(int signo);
    6. void *threadfunc(void *parm)
    7. {
    8. pthread_t tid = pthread_self();
    9. int rc;
    10. printf("Thread %u entered/n", tid);
    11. rc = sleep(30); /* 若有信号中断则返回剩余秒数 */
    12. printf("Thread %u did not get expected results! rc=%d/n", tid, rc);
    13. return NULL;
    14. }
    15. void *threadmasked(void *parm)
    16. {
    17. pthread_t tid = pthread_self();
    18. sigset_t mask;
    19. int rc;
    20. printf("Masked thread %lu entered/n", tid);
    21. sigfillset(&mask); /* 将所有信号加入mask信号集 */
    22. /* 向当前的信号掩码中添加mask信号集 */
    23. rc = pthread_sigmask(SIG_BLOCK, &mask, NULL);
    24. if (rc != 0)
    25. {
    26. printf("%d, %s/n", rc, strerror(rc));
    27. return NULL;
    28. }
    29. rc = sleep(15);
    30. if (rc != 0)
    31. {
    32. printf("Masked thread %lu did not get expected results! rc=%d /n", tid, rc);
    33. return NULL;
    34. }
    35. printf("Masked thread %lu completed masked work/n", tid);
    36. return NULL;
    37. }
    38. int main(int argc, char **argv)
    39. {
    40. int rc;
    41. int i;
    42. struct sigaction actions;
    43. pthread_t threads[NUMTHREADS];
    44. pthread_t maskedthreads[NUMTHREADS];
    45. printf("Enter Testcase - %s/n", argv[0]);
    46. printf("Set up the alarm handler for the process/n");
    47. memset(&actions, 0, sizeof(actions));
    48. sigemptyset(&actions.sa_mask); /* 将参数set信号集初始化并清空 */
    49. actions.sa_flags = 0;
    50. actions.sa_handler = sighand;
    51. /* 设置SIGALRM的处理函数 */
    52. rc = sigaction(SIGALRM,&actions,NULL);
    53. printf("Create masked and unmasked threads/n");
    54. for(i=0; i
    55. {
    56. rc = pthread_create(&threads[i], NULL, threadfunc, NULL);
    57. if (rc != 0)
    58. {
    59. printf("%d, %s/n", rc, strerror(rc));
    60. return -1;
    61. }
    62. rc = pthread_create(&maskedthreads[i], NULL, threadmasked, NULL);
    63. if (rc != 0)
    64. {
    65. printf("%d, %s/n", rc, strerror(rc));
    66. return -1;
    67. }
    68. }
    69. sleep(3);
    70. printf("Send a signal to masked and unmasked threads/n");
    71. /* 向线程发送SIGALRM信号 */
    72. for(i=0; i
    73. {
    74. rc = pthread_kill(threads[i], SIGALRM);
    75. rc = pthread_kill(maskedthreads[i], SIGALRM);
    76. }
    77. printf("Wait for masked and unmasked threads to complete/n");
    78. for(i=0; i
    79. rc = pthread_join(threads[i], NULL);
    80. rc = pthread_join(maskedthreads[i], NULL);
    81. }
    82. printf("Main completed/n");
    83. return 0;
    84. }
    85. void sighand(int signo)
    86. {
    87. pthread_t tid = pthread_self();
    88. printf("Thread %lu in signal handler/n", tid);
    89. return;
    90. }

    参考:

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

  • 相关阅读:
    AI语音机器人的重点功能配置之话术
    flink cdc 没有Replication client ,Replication slave权限,报错,处理
    离散数学复习:谓词逻辑
    redis安装(Windows和linux)
    浏览器开发者工具打开检测
    二十一、数组(1)
    泰拉瑞亚EasyBuildMod便捷建造模组开发详细过程
    Hibernate 环境搭建
    小球放盒子公式总结
    webpack5 使用Thead多进程打包提升打包构建速度
  • 原文地址:https://blog.csdn.net/denglin12315/article/details/126619152