热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

100多线程与信号

不知道你是否还记得之前在进程中的信号处理时,提到过阻塞信号集与未决信号集的概念,如果你已经忘记了,请参考《阻塞信号与未决信号》一文回忆一下

不知道你是否还记得之前在进程中的信号处理时,提到过阻塞信号集未决信号集的概念,如果你已经忘记了,请参考《阻塞信号与未决信号》一文回忆一下。


1. 多线程程序中的信号

在多线程中,每一个线程都有属于自己的阻塞信号集与未决信号集。当一个线程派生另一个线程的时候,会继承父线程的阻塞信号集,但是不会继承未决信号集,并且新线程会清空未决信号集。


2. 相关函数


2.1 设置阻塞信号集的函数

在多线程程序中,如果要设置线程的阻塞信号集,不能再使用 sigprocmask 函数,而应该使用 pthread_sigmask,其定义如下:

int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);

这个函数的用法和 sigprocmask 是一样的。


  • how 参数

    • SIG_BLOCK 该选项表示将 set 参数指示的信号集中的信号添加到进程阻塞集中
    • SIG_UNBLOCK 该选项与功能 SIG_BLOCK 相反,表示将线程阻塞信号集中指定的信号删除
    • SIG_SETMASK 该选项表示将线程阻塞信号集直接设定为你指定的 set
  • set 参数

表示你指定的信号集合


  • oldset

返回旧的阻塞信号集


  • 返回值 int

0 表示成功,-1 失败。


2.2 获取未决信号的函数

该函数仍然是 sigpending,没有变化。它的原型如下:

int sigpending(sigset_t *set);

2.3 信号发送函数

kill 函数只能给指定的进程发送函数,而是使用 pthread_kill 可以给指定的线程发送函数。它的原型如下:

int pthread_kill(pthread_t thread, int sig);

3. 实验

程序 th_sig 做了下面几个工作:


  • 在主线程阻塞了 SIGQUIT 信号
  • 在 fun1 线程中阻塞了 SIGINT 信号
  • 在 fun2 线程中什么也没阻塞

3.1 代码

// th_sig.c
#include
#include
#include
#include // 打印信号集
void printsigset(const sigset_t *set) {int i;for (i &#61; 1; i <&#61; 64; i&#43;&#43;) {if (i&#61;&#61;33) putchar(&#39; &#39;);if (sigismember(set, i) &#61;&#61; 1)putchar(&#39;1&#39;);elseputchar(&#39;0&#39;);}puts("");
}// fun1 线程
void* fun1(void* arg) {// 阻塞 SIGINT 信号sigset_t mask, st; sigemptyset(&mask);sigaddset(&mask, SIGINT);pthread_sigmask(SIG_BLOCK, &mask, NULL);while(1) {printf("I&#39;m fun1:\t");sigpending(&st);printsigset(&st);sleep(3);}
}// fun2 线程
void* fun2(void* arg) {sigset_t st; while(1) {printf("I&#39;m fun2:\t");sigpending(&st);printsigset(&st);sleep(3);}
}int main() {// 创建线程前阻塞 SIGQUITsigset_t mask, st; sigemptyset(&mask);sigaddset(&mask, SIGQUIT);pthread_sigmask(SIG_BLOCK, &mask, NULL);pthread_t tid1, tid2;pthread_create(&tid1, NULL, fun1, NULL);pthread_create(&tid2, NULL, fun2, NULL);sleep(2);pthread_kill(tid1, SIGINT);while(1) {printf("I&#39;m main:\t");sigpending(&st);printsigset(&st);sleep(3);}return 0;
}

3.2 编译与运行


  • 编译

$ gcc th_sig.c -o th_sig -lpthread

  • 运行



这里写图片描述
图1 运行结果

关于图 1 的说明&#xff1a;左侧是线程的名字&#xff0c;右侧是打印的未决队列&#xff0c;也就是未被信号处理函数处理的信号。其中第 1 列是 SIGHUP 信号&#xff0c;第 2 列表示 SIGINT 信号&#xff0c;第 3 列表示 SIGQUIT 信号。

当主线程休眠 2 秒后&#xff0c;给线程 fun1 发送了一个 SIGINT 信号&#xff0c;此时 fun1 的未决信号集中第 2 列变成了 1 &#xff08;图 1 上的第 5 行&#xff09;。

在后面某个时候&#xff0c;按下了 CTRL &#43; \&#xff0c;表示发送信号 SIGQUIT 给前台进程组中的进程。接下来&#xff0c;可以发现&#xff0c;所有的线程未决信号集中的第 3 列都变成了 1. 这说明了两件事&#xff1a;


  • 线程继承了父线程阻塞信号集
  • kill 信号会发送给进程中的所有线程

4. 总结


  • 每个线程有自己的阻塞信号集与未决信号集
  • 线程会继承父线程的阻塞信号集&#xff0c;新线程会清空未决信号集
  • pthread_kill 发送信号给指定线程
  • kill 发送信号给所有线程

推荐阅读
  • 2012年9月12日优酷土豆校园招聘笔试题目解析与备考指南
    2012年9月12日,优酷土豆校园招聘笔试题目解析与备考指南。在选择题部分,有一道题目涉及中国人的血型分布情况,具体为A型30%、B型20%、O型40%、AB型10%。若需确保在随机选取的样本中,至少有一人为B型血的概率不低于90%,则需要选取的最少人数是多少?该问题不仅考察了概率统计的基本知识,还要求考生具备一定的逻辑推理能力。 ... [详细]
  • 寒假作业解析:第三周 2月12日 第7题
    尽快完成之前的练习任务!每日一练2.1 Problem A Laurenty and Shop 的题目要求是选择两条不同的路线以最小化总的等待时间。简要分析:通过对比不同路线的等待时间,可以找到最优解。此问题可以通过动态规划或贪心算法来解决,具体取决于路线的复杂性和约束条件。 ... [详细]
  • 本文对常见的字符串哈希函数进行了全面分析,涵盖了BKDRHash、APHash、DJBHash、JSHash、RSHash、SDBMHash、PJWHash和ELFHash等多种算法。这些哈希函数在不同的应用场景中表现出各异的性能特点,通过对比其算法原理、计算效率和碰撞概率,为实际应用提供了有价值的参考。 ... [详细]
  • C++入门必备:首个博客知识点汇总
    本文总结了C++初学者需要掌握的关键知识点,特别强调了成员类型的区分。其中,protected成员与private成员在本类中的作用相同,但protected成员允许派生类的成员函数访问,而private成员则不允许。此外,文章还介绍了其他重要的C++基础概念,如类的构造函数、析构函数以及继承机制,为初学者提供了一个全面的学习指南。 ... [详细]
  • 本文详细探讨了Zebra路由软件中的线程机制及其实际应用。通过对Zebra线程模型的深入分析,揭示了其在高效处理网络路由任务中的关键作用。文章还介绍了线程同步与通信机制,以及如何通过优化线程管理提升系统性能。此外,结合具体应用场景,展示了Zebra线程机制在复杂网络环境下的优势和灵活性。 ... [详细]
  • 如何利用正则表达式(regexp)实现高效的模式匹配?本文探讨了正则表达式在编程中的应用,并分析了一个示例程序中存在的问题。通过具体的代码示例,指出该程序在定义和使用正则表达式时的不当之处,旨在帮助读者更好地理解和应用正则表达式技术。 ... [详细]
  • GDB 使用心得与技巧总结
    在使用 GDB 进行调试时,可以采用以下技巧提升效率:1. 通过设置 `set print pretty on` 来美化打印输出,使数据结构更加易读;2. 掌握常见数据结构的打印方法,如链表、树等;3. 利用 `info locals` 命令查看当前作用域内的所有局部变量;4. 在需要进行类型强制转换时,正确使用语法,例如 `p (Test::A *) pObj`。这些技巧能够显著提高调试的便捷性和准确性。 ... [详细]
  • Prim算法在处理稠密图时表现出色,尤其适用于边数远多于顶点数的情形。传统实现的时间复杂度为 \(O(n^2)\),但通过引入优先队列进行优化,可以在点数为 \(m\)、边数为 \(n\) 的情况下显著降低时间复杂度,提高算法效率。这种优化方法不仅能够加速最小生成树的构建过程,还能在大规模数据集上保持良好的性能表现。 ... [详细]
  • BZOJ4240 Gym 102082G:贪心算法与树状数组的综合应用
    BZOJ4240 Gym 102082G 题目 "有趣的家庭菜园" 结合了贪心算法和树状数组的应用,旨在解决在有限时间和内存限制下高效处理复杂数据结构的问题。通过巧妙地运用贪心策略和树状数组,该题目能够在 10 秒的时间限制和 256MB 的内存限制内,有效处理大量输入数据,实现高性能的解决方案。提交次数为 756 次,成功解决次数为 349 次,体现了该题目的挑战性和实际应用价值。 ... [详细]
  • 在操作系统中,阻塞状态与挂起状态有着显著的区别。阻塞状态通常是指进程因等待某一事件(如I/O操作完成)而暂时停止执行,而挂起状态则是指进程被系统暂时移出内存,以释放资源或降低系统负载。此外,本文还深入分析了`sleep()`函数的实现机制,探讨了其在不同操作系统中的具体实现方式及其对进程调度的影响。通过这些分析,读者可以更好地理解操作系统如何管理进程的不同状态以及`sleep()`函数在其中的作用。 ... [详细]
  • 在解决区间相关问题时,我发现自己经常缺乏有效的思维方式,即使是简单的题目也常常需要很长时间才能找到解题思路,而一旦得到提示便能迅速理解。题目要求对一个包含n个元素的数组进行操作,并给出一个参数k,具体任务是…… ... [详细]
  • 题目链接:http://codeforces.com/gym/101190/attachments题意:在一个共享三轮车站点,某些用户需要租用车辆。该问题涉及如何通过离线查询和排序优化策略来高效地管理和分配车辆资源。具体来说,需要设计一种算法,在满足所有用户需求的同时,最小化总等待时间和资源浪费。通过合理的数据结构和算法优化,可以显著提高系统的整体性能和用户体验。 ... [详细]
  • 在 Windows 10 环境中,通过配置 Visual Studio Code (VSCode) 实现基于 Windows Subsystem for Linux (WSL) 的 C++ 开发,并启用智能代码提示功能。具体步骤包括安装 VSCode 及其相关插件,如 CCIntelliSense、TabNine 和 BracketPairColorizer,确保在 WSL 中顺利进行开发工作。此外,还详细介绍了如何在 Windows 10 中启用和配置 WSL,以实现无缝的跨平台开发体验。 ... [详细]
  • 在CentOS上部署和配置FreeSWITCH
    在CentOS系统上部署和配置FreeSWITCH的过程涉及多个步骤。本文详细介绍了从源代码安装FreeSWITCH的方法,包括必要的依赖项安装、编译和配置过程。此外,还提供了常见的配置选项和故障排除技巧,帮助用户顺利完成部署并确保系统的稳定运行。 ... [详细]
  • ubuntu下基于c++的opencv学习
    一、环境配置1、安装opencv2、makefile编写makefile模板,与c文件在同一个目录下,用make指令生成可执行文件,然后运 ... [详细]
author-avatar
筱庆儿宝贝
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有